MST

星途 面试题库

面试题:Java中如何利用多线程提升与多核处理器适配性

在Java开发中,为了更好地适应多核处理器,常使用多线程技术。请描述在Java里创建多线程的两种常见方式,并说明如何通过线程池来管理多线程以提高系统性能和与多核处理器的适配性。
49.7万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

创建多线程的两种常见方式

  1. 继承Thread类
    • 定义一个类继承Thread类。
    • 重写run()方法,在该方法中编写线程执行的代码。
    • 创建该类的实例,调用start()方法启动线程。 示例代码:
class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("This is a thread created by extending Thread class.");
    }
}

public class Main {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myThread.start();
    }
}
  1. 实现Runnable接口
    • 定义一个类实现Runnable接口。
    • 实现run()方法,编写线程执行的代码。
    • 创建该类的实例,将其作为参数传递给Thread类的构造函数,然后调用start()方法启动线程。 示例代码:
class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("This is a thread created by implementing Runnable interface.");
    }
}

public class Main {
    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();
        Thread thread = new Thread(myRunnable);
        thread.start();
    }
}

通过线程池管理多线程提高系统性能和与多核处理器的适配性

  1. 使用线程池的优势
    • 降低资源消耗:避免频繁创建和销毁线程带来的开销。
    • 提高响应速度:当任务到达时,无需等待线程创建即可执行。
    • 提高线程的可管理性:可以对线程进行统一的调度和监控。
  2. Java中的线程池实现
    • 使用ExecutorService接口和ThreadPoolExecutorThreadPoolExecutorExecutorService接口的实现类,通过它可以创建自定义参数的线程池。 构造函数参数:
      • corePoolSize:线程池中核心线程的数量,即使线程处于空闲状态,也不会被销毁,除非设置了allowCoreThreadTimeOuttrue
      • maximumPoolSize:线程池中允许的最大线程数量。
      • keepAliveTime:当线程数大于核心线程数时,多余的空闲线程等待新任务的最长时间,超过这个时间,多余线程将被销毁。
      • unitkeepAliveTime的时间单位。
      • workQueue:用于存储等待执行任务的队列。 示例代码:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class Main {
    public static void main(String[] args) {
        // 创建线程池
        ExecutorService executorService = new ThreadPoolExecutor(
                2, 
                4, 
                10, 
                TimeUnit.SECONDS, 
                new java.util.concurrent.LinkedBlockingQueue<>());
        for (int i = 0; i < 10; i++) {
            int taskNumber = i;
            executorService.submit(() -> {
                System.out.println("Task " + taskNumber + " is running on thread " + Thread.currentThread().getName());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        executorService.shutdown();
        try {
            if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {
                executorService.shutdownNow();
                if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {
                    System.err.println("Pool did not terminate");
                }
            }
        } catch (InterruptedException ie) {
            executorService.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }
}
- **使用`Executors`工具类创建常见类型的线程池**:
    - **`Executors.newFixedThreadPool(int nThreads)`**:创建一个固定大小的线程池,线程池中的线程数量始终保持为`nThreads`。适用于负载比较稳定,需要控制并发数的场景。
    - **`Executors.newCachedThreadPool()`**:创建一个可缓存的线程池,如果线程池中的线程空闲时间超过60秒,线程将被回收。适用于任务执行时间短,并发量变化大的场景。
    - **`Executors.newSingleThreadExecutor()`**:创建一个单线程的线程池,所有任务按照提交顺序依次执行。适用于需要保证顺序执行,并且资源有限的场景。

示例代码:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {
    public static void main(String[] args) {
        // 创建固定大小线程池
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
        for (int i = 0; i < 10; i++) {
            int taskNumber = i;
            fixedThreadPool.submit(() -> {
                System.out.println("Task " + taskNumber + " is running on thread " + Thread.currentThread().getName());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        fixedThreadPool.shutdown();

        // 创建可缓存线程池
        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
            int taskNumber = i;
            cachedThreadPool.submit(() -> {
                System.out.println("Task " + taskNumber + " is running on thread " + Thread.currentThread().getName());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        cachedThreadPool.shutdown();

        // 创建单线程线程池
        ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 10; i++) {
            int taskNumber = i;
            singleThreadExecutor.submit(() -> {
                System.out.println("Task " + taskNumber + " is running on thread " + Thread.currentThread().getName());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        singleThreadExecutor.shutdown();
    }
}
  1. 与多核处理器的适配
    • 根据处理器核心数动态调整线程池参数,例如核心线程数可以设置为处理器核心数,以充分利用多核处理器的计算能力。
    • 通过合理设置线程池的最大线程数和队列容量,避免过多线程竞争资源导致性能下降,确保每个核心都能高效处理任务。