一、什么是线程池?
线程池是一种多线程编程工具,它可以提供一种高效的线程复用机制。在使用线程池时,任务将被提交到线程池中,线程池会自动分配一个线程来执行任务。当任务执行完成后,线程将被放回线程池中,等待下一次任务的执行。通过使用线程池,可以避免频繁创建和销毁线程,从而提高系统的性能和稳定性。
二、线程池有哪些常见的参数?
Java 中的线程池有以下常见的参数:
corePoolSize:核心线程数。线程池中一直存活的线程数量,即使它们是空闲的。
maximumPoolSize:最大线程数。线程池中允许的最大线程数量。
keepAliveTime:线程空闲时间。当线程池中的线程数量超过 corePoolSize 时,多余的线程在空闲时间达到 keepAliveTime 后会被销毁,直到线程池中的线程数量重新达到 corePoolSize。
unit:空闲时间的单位。通常为 TimeUnit.SECONDS 或 TimeUnit.MILLISECONDS。
workQueue:工作队列。用于存储等待执行的任务的阻塞队列。
threadFactory:线程工厂。用于创建新线程。
handler:饱和策略。当工作队列和线程池都已满时,用于处理新任务的拒绝策略。
三、如何创建线程池?
在 Java 中,可以使用 ThreadPoolExecutor 类来创建线程池。ThreadPoolExecutor 类提供了很多构造函数,下面是其中一个常见的构造函数:
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
该构造函数的参数分别是线程池的核心线程数、最大线程数、线程空闲时间、空闲时间的单位、工作队列、线程工厂和饱和策略
- import java.util.concurrent.*;
-
- public class ThreadPoolExample {
- public static void main(String[] args) {
- int corePoolSize = 2;
- int maxPoolSize = 5;
- long keepAliveTime = 60;
- TimeUnit unit = TimeUnit.SECONDS;
- BlockingQueue
workQueue = new ArrayBlockingQueue<>(10); - ThreadFactory threadFactory = Executors.defaultThreadFactory();
- RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();
-
- ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maxPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
-
- executor.execute(new Task());
- executor.execute(new Task());
- executor.execute(new Task());
-
- executor.shutdown();
- }
-
- static class Task implements Runnable {
- @Override
- public void run() {
- System.out.println(Thread.currentThread().getName() + " is running");
- }
- }
- }
四、线程池的运行原理是什么?
线程池的运行原理如下:
当线程池接收到新的任务时,线程池会在工作队列中添加任务。
如果当前线程池中的线程数量小于核心线程数,线程池会创建新的线程来执行任务。
如果当前线程池中的线程数量达到核心线程数,线程池会将任务放入工作队列中等待执行。
如果工作队列已满,但是当前线程池中的线程数量小于最大线程数,线程池会创建新的线程来执行任务。
如果工作队列已满,并且当前线程池中的线程数量已达到最大线程数,此时饱和策略就会起作用,用于处理新任务的拒绝策略。
当线程执行完任务后,如果线程空闲时间超过设定的时间,线程就会被销毁。
五、线程池中的饱和策略有哪些?
Java 中线程池的饱和策略有以下几种:
AbortPolicy:抛出 RejectedExecutionException 异常。
CallerRunsPolicy:由调用线程处理该任务。
DiscardOldestPolicy:丢弃最早的任务,然后执行新的任务。
DiscardPolicy:直接丢弃新的任务。
可以通过 ThreadPoolExecutor 的构造方法来指定饱和策略。
六、线程池中的工作队列有哪些?
Java 中线程池的工作队列有以下几种:
ArrayBlockingQueue:基于数组的有界阻塞队列。
LinkedBlockingQueue:基于链表的无界阻塞队列。
SynchronousQueue:不存储元素的阻塞队列,每个插入操作必须等待另一个线程的删除操作。
PriorityBlockingQueue:具有优先级的无界阻塞队列。
可以通过 ThreadPoolExecutor 的构造方法来指定工作队列。
七、如何优雅地关闭线程池?
在 Java 中,可以通过调用 ThreadPoolExecutor 的 shutdown() 方法来优雅地关闭线程池。该方法将会按照先前提交的任务的顺序来执行任务,并且不允许提交新的任务。当所有任务执行完毕后,线程池将自动关闭。
- import java.util.concurrent.*;
-
- public class ShutdownThreadPoolExample {
- public static void main(String[] args) {
- int corePoolSize = 2;
- int maxPoolSize = 5;
- long keepAliveTime = 60;
- TimeUnit unit = TimeUnit.SECONDS;
- BlockingQueue
workQueue = new ArrayBlockingQueue<>(10); - ThreadFactory threadFactory = Executors.defaultThreadFactory();
- RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();
-
- ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maxPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
-
- executor.execute(new Task());
- executor.execute(new Task());
- executor.execute(new Task());
-
- executor.shutdown();
- }
-
- static class Task implements Runnable {
- @Override
- public void run() {
- System.out.println(Thread.currentThread().getName() + " is running");
- }
- }
- }