线程池的5种状态 状态分类 RUNNING 线程池处在 RUNNING 状态时,能够接收新任务,以及对已添加的任务进行处理。该状态是线程池的初始状态,线程池一旦被创建,就处于 RUNNING 状态
SHUTDOWN 线程池处于 SHUTDOWN 状态时,不接收新任务,但能处理等待队列中的任务。线程池在 RUNNING 状态下,调用 shutdown() 方法,会变成 SHUTDOWN 状态。
STOP 线程池处于 STOP 状态时,不接收新任务,不再处理等待队列中的任务,并且会中断正在处理的任务线程池在 RUNNING 状态下,调用 shutdownNow() 方法,变为 STOP 状态
TIDYING 所有的任务都销毁了,工作线程数量为0,线程池的状态在转换为 TIDYING 状态时,会执行钩子方法 terminated()线程池在 SHUTDOWN 状态时,阻塞队列为空并且线程池中执行的任务也为空时,就会由 SHUTDOWN 状态变为 TIDYING 状态;线程池在 STOP 状态时,线程池中执行的任务为空时,就会由 STOP 状态变为 TIDYING 。
TERMINATED terminated() 方法执行之后,线程池彻底终止,就变成 TERMINATED 状态。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 public XSSFWorkbook createExcel (List<DataHistory> list, ArrayList<String> titles) throws IOException { XSSFWorkbook workbook = new XSSFWorkbook (); XSSFSheet sheet = workbook.createSheet(); XSSFCellStyle style = workbook.createCellStyle(); style.setWrapText(true ); XSSFRow row = sheet.createRow(0 ); int columnIndex = 0 ; for (String value : titles) { XSSFCell cell = row.createCell(columnIndex++); cell.setCellValue(value); } if (list != null ) { int rowNum = 1 ; for (DataHistory dataHistory : list) { columnIndex = 0 ; XSSFRow newRow = sheet.createRow(rowNum++); ExecutorService es = Executors.newCachedThreadPool(); CountDownLatch doneSignal = new CountDownLatch (5 ); try { for (String value : titles) { XSSFCell cell = newRow.createCell(columnIndex++); es.submit( new Runnable () { @Override public void run () { cell.setCellValue(getValues(value, dataHistory)); doneSignal.countDown(); } } ); } doneSignal.await(); es.shutdown(); } catch (Exception e) { e.printStackTrace(); } } } return workbook; }
CountDownLatch
是一个同步工具类,用来协调多个线程之间的同步,能够使一个线程在等待另外一些线程完成各自工作之后,再继续执行。使用一个计数器进行实现。计数器初始值为线程的数量。当每一个线程完成自己任务后,计数器的值就会减一。当计数器的值为0时,表示所有的线程都已经完成一些任务,然后在CountDownLatch上等待的线程就可以恢复执行接下来的任务
线程池实现方式 Executor Executor 接口是线程池框架中最基础的部分,定义了一个 void execute(Runnable command)
方法,代表提交一个任务,由线程池来执行这个任务。
ExecutorService Executor 下有一个重要子接口 ExecutorService,其中定义了一些可以操作线程池的方法:
public interface ExecutorService extends Executor {
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 void shutdown () ; List<Runnable> shutdownNow () ; boolean isShutdown () ; boolean isTerminated () ; boolean awaitTermination (long timeout, TimeUnit unit) ; <T> Future submit (Callable<T> task) ; <T> Future submit (Runnalbe task, T result) ; Future<?> submit(Runnable task); <T> List<Future<T>> invokeAll (Collection<? extends Callable<T>> tasks) ; <T> List<Future<T>> invokeAll (Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) ; <T> invokeAny(Collection<? extends Callable <T>> tasks); <T> T invokeAny (Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) ;
ThreadPoolExecutor JDK 中线程池的默认实现,实现了线程池中的基本方法,可以直接使用,或者基本它扩展,来实现我们需要的功能,下面这个是 ThreadPoolExecutor
的核心构造函数,其他的构造函数最终都会走到该构造方法
1 2 3 4 5 6 7 public ThreadPoolExecutor (int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectExecutionHandler handler
参数说明
corePoolSize
是线程池中的核心线程数 ,maxinumPoolSize
是线程池中允许的最大线程数 ,当当前正在运行的线程数小于 corePoolSize
值,新提交任务时,会创建一个新的线程来执行,即使有空闲的线程;当当前正在运行的线程数大于 corePoolSize
值,且小于maximumPoolSize
值,新任务会提交到等待队列中,直到等待队列 满了,才会创建新的线程执行任务。
keepAliveTime
线程允许的最大空闲时间。且默认情况下,只会在超时后,销毁非核心线程。也可以通过调用 allowCoreThreadTimeOut(true)
方法,来将这种策略应用于核心线程
unit
,keepAliveTime
的时间单位
workQueue
是用来保存等待被执行任务的阻塞队列,通常和线程池的大小对应调整。
threadFactory
创建线程的工厂类,用来创建新线程
handler
线程池的拒绝策略,当线程池处于关闭状态,或者阻塞队列满了,而且线程数量已经达到了 maximumPoolSize
,再提交任务时,就会执行当前指定的策略