线程池使用详解

目录

原理

好处

创建线程池

构造方法

参数详解

int corePoolSize

int maximumPoolSize

long keepAliveTime

TimeUnit unit

BlockingQueue workQueue

ThreadFactory threadFactory

RejectedExecutionHandler hanler

执行任务

execute()

submit()

并发操作

关闭线程池

shutdown()

shutdownNow()


原理

线程池就是一个存放已经创建好的线程的池子,当有任务提交给线程池执行时,线程池中的某个线程会主动执行该任务。如果线程池中的线程数量不够应付数量众多的任务时,需要自动扩充新的线程到线程池中,数量是有限的。当任务比较少的时候,线程池中的线程能够自动回收,释放资源。

好处

降低资源消耗:通过重复利用已创建的线程降低线程创建和销毁造成的消耗。

提高响应速度:当任务到达时,任务可以不需要等到线程创建就能立即执行。

提高线程的可管理性:线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一分配、调优和监控。

创建线程池

通过java.util.concurrent.ThreadPoolExecutor来创建一个线程池。

构造方法

//五个参数的构造函数

public ThreadPoolExecutor(int corePoolSize,

                          int maximumPoolSize,

                          long keepAliveTime,

                          TimeUnit unit,

                          BlockingQueue workQueue)

 

//六个参数的构造函数-1

public ThreadPoolExecutor(int corePoolSize,

                          int maximumPoolSize,

                          long keepAliveTime,

                          TimeUnit unit,

                          BlockingQueue workQueue,

                          ThreadFactory threadFactory)

 

//六个参数的构造函数-2

public ThreadPoolExecutor(int corePoolSize,

                          int maximumPoolSize,

                          long keepAliveTime,

                          TimeUnit unit,

                          BlockingQueue workQueue,

                          RejectedExecutionHandler handler)

 

//七个参数的构造函数

public ThreadPoolExecutor(int corePoolSize,

                          int maximumPoolSize,

                          long keepAliveTime,

                          TimeUnit unit,

                          BlockingQueue workQueue,

                          ThreadFactory threadFactory,

                          RejectedExecutionHandler handler)

参数详解

int corePoolSize

该线程池中核心线程的最大数量,即默认情况下一直会存活在线程池中,即使处于闲置状态。如果当前线程总数小于corePoolSize,新建的线程是核心线程,否则是非核心线程。

int maximumPoolSize

该线程池中线程总数最大值。

long keepAliveTime

表示线程没有任务执行时最多保持多久时间会终止。默认情况下,只有当线程池中的线程数大于corePoolSize时,keepAliveTime才会起作用,即当线程池中的线程数大于corePoolSize时,如果一个线程空闲的时间达到keepAliveTime,则会终止,直到线程池中的线程数不超过corePoolSize。但是如果调用了allowCoreThreadTimeOut(boolean)方法,在线程池中的线程数不大于corePoolSize时,keepAliveTime参数也会起作用,直到线程池中的线程数为0。

TimeUnit unit

参数keepAliveTime的时间单位

TimeUnit是一个枚举类型,其包括:
NANOSECONDS : 1微毫秒 = 1微秒 / 1000
MICROSECONDS : 1微秒 = 1毫秒 / 1000
MILLISECONDS : 1毫秒 = 1秒 /1000
SECONDS : 秒
MINUTES : 分
HOURS : 小时
DAYS : 天

BlockingQueue workQueue

该线程池中的任务队列,用来存储等待执行的任务。

ThreadFactory threadFactory

线程工厂,主要用来创建线程,一般用不上。

RejectedExecutionHandler hanler

表示当拒绝处理任务时的策略,有以下四种取值:

 

ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。

ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。

ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)

ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务

执行任务

execute()

这个方法是顶层接口Executor中声明的方法,在ThreadPoolExecutor类中进行了具体实现,参数是Runnable,通过这个方法可以向线程池提交一个任务,交由线程池去执行。

submit()

Submit是在接口ExecutorService中声明的方法,在ThreadPoolExecutor类的抽象父类AbstractExecutorService中进行了具体实现。这个方法也是用来向线程池提交任务的,参数是Runnable,但是它和execute()方法不同,它能够返回任务执行的结果,去看submit()方法的实现,会发现它实际上还是调用的execute()方法,只不过它利用了Future来获取任务执行结果。

并发操作

可以和CountDownLatch配合使用:

1、主线程使用await() 阻塞住,直到所有子线程都执行完毕了,才会继续向下执行。

2、所有子线程共享同一个 CountDownLatch变量,需要执行的线程总数。

3、所有子线程的finally块中,必须要countDown() ,确保 "无论 正确、异常 都会countDown",否则主线程会由于"某一个 子任务 没有countDown过,就执行结束了,导致CountDownLatch最终无法被countDown 到 0 ,而被永远挂住。

关闭线程池

shutdown()

不会立即终止线程池,而是要等所有任务缓存队列中的任务都执行完后才终止,但再也不会接受新的任务。

shutdownNow()

立即终止线程池,并尝试打断正在执行的任务,并且清空任务缓存队列,返回尚未执行的任务。

你可能感兴趣的:(多线程)