单线程就不说了因为简单,并且 在实际的生产环境中一般必须来说 线程资源都是由线程池提供线程资源的。

线程池的好处

  • 重用存在的线程,减少对象创建、消亡的开销,性能好
  • 可有效控制最大并发线程数,提高系统资源利用率,同时可以避免过多资源竞争,避免阻塞。
  • 提供定时执行、定期执行、单线程、并发数控制等功能。

在线程池的类图中,我们最常使用的是最下边的Executors,用它来创建线程池使用线程。那么在上边的类图中,包含了一个Executor框架,它是一个根据一组执行策略的调用调度执行和控制异步任务的框架,目的是提供一种将任务提交与任务如何运行分离开的机制。它包含了三个executor接口:

  • Executor:运行新任务的简单接口
  • ExecutorService:扩展了Executor,添加了用来管理执行器生命周期和任务生命周期的方法
  • ScheduleExcutorService:扩展了ExecutorService,支持Future和定期执行任务

 来说一下实际应用:

 

【强制】线程池不允许使用 Executors去创建,而是通过 ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。说明:Executors返回的线程池对象的弊端如下:

1)FixedThreadPool和 SingleThreadPool:

  允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。

2)CachedThreadPool和 ScheduledThreadPool:

  允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM

线程池核心类-ThreadPoolExecutor

参数说明:ThreadPoolExecutor一共有七个参数,这七个参数配合起来,构成了线程池强大的功能。

  • corePoolSize:核心线程数量
  • maximumPoolSize:线程最大线程数
  • workQueue:阻塞队列,存储等待执行的任务,很重要,会对线程池运行过程产生重大影响
  • keepAliveTime:线程没有任务执行时最多保持多久时间终止(当线程中的线程数量大于corePoolSize的时候,如果这时没有新的任务提交核心线程外的线程不会立即销毁,而是等待,直到超过keepAliveTime)
  • unit:keepAliveTime的时间单位
  • threadFactory:线程工厂,用来创建线程,有一个默认的工场来创建线程,这样新创建出来的线程有相同的优先级,是非守护线程、设置好了名称)
初始化方法:由七个参数组合成四个初始化方法 
其他方法:
1 execute() 提交任务,交给线程池执行
2 submit() 提交任务,能够返回执行结果 execute+Future
3 shutdown() 关闭线程池,等待任务都执行完
4 shutdownNow() 关闭线程池,不等待任务执行完
5 getTaskCount() 线程池已执行和未执行的任务总数
6 getCompleteTaskCount() 已完成的任务数量
7 getPoolSize() 线程池当前的线程数量
8 getActiveCount() 当前线程池中正在执行任务的线程数量
  • running:能接受新提交的任务,也能处理阻塞队列中的任务
  • shutdown:不能处理新的任务,但是能继续处理阻塞队列中任务
  • stop:不能接收新的任务,也不处理队列中的任务
  • tidying:如果所有的任务都已经终止了,这时有效线程数为0
  • terminated:最终状态
 
 

4种线程池

1. Executors.newCachedThreadPool 
创建一个可缓存的线程池,如果线程池的长度超过了处理的需要,可以灵活回收空闲线程。如果没有可回收的就新建线程。

 2.Executors.newFixedThreadPool 
定长线程池,可以线程现成的最大并发数,超出在队列等待

3.Executors.newSingleThreadExecutor 
单线程化的线程池,用唯一的一个共用线程执行任务,保证所有任务按指定顺序执行(FIFO、优先级…)

4.Executors.newScheduledThreadPool 
定长线程池,支持定时和周期任务执行
 
这是Executors 创建常用的 4种线程池,但是我在上面说了 需要用ThreadPoolExecutor 来创建,那么怎么办呢? 那我们一起看一下源码把
 
1. Executors.newCachedThreadPool 
ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();

源码:
    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

 2.Executors.newFixedThreadPool 

ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(5);

public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }

3.Executors.newSingleThreadExecutor 

ExecutorService newSingleThreadExecutor = Executors.newSingleThreadExecutor();

源码:
  public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

4.Executors.newScheduledThreadPool 

 public ScheduledThreadPoolExecutor(int corePoolSize,
                                       ThreadFactory threadFactory) {
//此处super指的是ThreadPoolExecutor super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue(), threadFactory); }

 ScheduledExecutorService提供了三种方法可以使用: 

 

scheduleAtFixedRate:以指定的速率执行任务 
scheduleWithFixedDelay:以指定的延迟执行任务 
举例:

executorService.scheduleAtFixedRate(new Runnable() {
    @Override
    public void run() {
        log.warn("schedule run");
    }
}, 1, 3, TimeUnit.SECONDS);//延迟一秒后每隔3秒执行

小扩展:延迟执行任务的操作,java中还有Timer类同样可以实现

Timer timer = new Timer();
timer.schedule(new TimerTask() {
    @Override
    public void run() {
        log.warn("timer run");
    }
}, new Date(), 5 * 1000);
 
 
10-01 17:06