Java中的线程池(未完

169 阅读3分钟

Question

使用线程池如何实现join

使用优先级?

理论部分

线程池的优势

避免创建,销毁线程带来的损耗 对线程进行统一的调度管理

Executors封装好的线程池

ExecutorService executor = Executors.newFixedThreadPool(3);

newFixedThreadPool()

线程数目固定大小的线程池

return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(),threadFactory);

使用的是无界任务阻塞队列,任务有可能会无限堆积

newCachedThreadPool()

newScheduledThreadPool()

newSingleThreadExecutor()

ThreadPoolExecutor自定义线程池

八大参数

  1. corePoolSize 线程池的基本大小
  2. maximumPoolSize 线程池的最大线程数
  3. keepAliveTime 空闲线程保持存活的时间
  4. TimeUnit unit
  5. BlockingQueue workQueue
  6. ThreadFactory threadFactory
  7. RejectedExecutionHandler handler

RejectedExecutionHandler handler

当线程池中的线程达到了maximumPoolSize,而任务队列也满了的时候,新增任务时的应对策略

AbortPolicy(抛出异常

AbortPolicy 中止策略(默认策略):抛出RejectedExecutionException异常

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
    throw new RejectedExecutionException("Task " + r.toString() + " rejected from " + e.toString());
} 

DiscardPolicy(啥也不做

DiscardPolicy抛弃策略:啥也不做

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
} 

DiscardOldestPolicy(抛弃旧任务策略

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
              if (!e.isShutdown()) {
                  e.getQueue().poll();
                  e.execute(r);
              }
  } 

自定义策略

也可自定义策略:方法为实现RejectedExecutionHandler接口,重写rejectedExecution方法

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
    ystem.out.println(“球球你不要再加任务了”);
    //打印日志,抛弃任务
} 

核心设计的三大参数

  1. corePoolSize 线程池的基本大小
  2. maximumPoolSize 线程池中的最大线程数
  3. workQueue 任务队列

corePoolSize

任务提交到线程池的时候,线程池会创建线程来完成任务,即使当前存在空闲线程,直到线程数大于corePoolSize的时候

maximumPoolSize

线程池中最大的线程数

workque

ArrayBlockingQueue; LinkedBlockingQueue; SynchronousQueue; PriorityBlockingQueue

LinkedBlockingQueue 无界队列

任务可以在任务队列中无限堆积 吞吐量相比ArrayBlockingQueue要高一点

ArrayBlockingQueue 有界队列

SynchronousQueue

PriorityBlockingQueue

具备优先级的无限阻塞队列

工作流程

当任务提交给ThreadPoolExecutor 线程池中, 先检查核心线程数是否已经全部使用,如果没有则交由核心线程去执行任务, 如果核心线程数已经全部占用,则将任务添加到队列里面, 如果队列已经占满,比较当前线程池的中线程的数量是不是与超过maximumPoolSize, 如果没有查过则创建线程去执行, 也就是说线程池最多可以接受多少任务呢?就是maximumPoolSize+队列的大小。 当线程池中的线程的数量大于corePoolSize数量有空闲线程则执行回收,回收时间是keepAliveTime,单位是unit,都是初始化的时候设置的

提交任务

可以使用execute()(提交不需要返回值的任务) 可以使用submit()(提交需要返回值的任务)

execute()

submit()

线程池会返回一个future类型的对象

合理地配置线程池

CPU密集型的任务,线程数尽可能少:CPU个数+1个线程 IO密集型的任务,线程数可以多 2 * CPU个数 尽量使用有界队列

监控线程池

Example

本文使用 mdnice 排版