Java中的线程池

为什么要有线程池?

通过对线程的学习,我们在使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题,如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。
此时就需要引入线程池的概念,在Java中可以通过线程池使得线程可以复用,就是执行完一个任务,并不被销毁,而是可以继续执行其他的任务。

在多线程编程中,合理利用线程池有三个好处:

  1. 降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
  2. 提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
  3. 提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。

一、Java中的ThreadPoolExecutor类

java.uitl.concurrent.ThreadPoolExecutor类是线程池中最核心的一个类,因此如果要透彻地了解Java中的线程池,必须先了解这个类。我们先看看这个类的具体实现:

由源码我们可以看到ThreadPoolExecutor类继承自AbstractExecutorService类,并且提供了四种构造方法,前三种构造方法都是通过调用第四个构造方法进行的初始化操作。

public class ThreadPoolExecutor extends AbstractExecutorService{


	//第一种
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }
    //第二种
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             threadFactory, defaultHandler);
    }
    //第三种
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              RejectedExecutionHandler handler) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), handler);
    }
    //第四种
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

解释下构造函数中各个参数的意义:

  • corePoolSize:核心池的大小,池中所保存的线程数
  • maximumPoolSize:线程池最大线程数
  • keepAliveTime:表示线程没有任务执行时最多保持多久时间会终止
  • unit:参数keepAliveTime的时间单位
  • workQueue:一个阻塞队列,用来存储等待执行的任务
    一般有以下选择:
(1) ArrayBlockingQueue:基于数组结构的有界阻塞队列
(2) LinkedBlockingQuene:基于链表结构的阻塞队列
(3) SynchronousQuene:一个不存储元素的阻塞队列,每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态
(4) priorityBlockingQuene:具有优先级的无界阻塞队列

  • threadFactory:线程工厂,主要用来创建线程
  • handler:表示当拒绝处理任务时的策略,四种
(1)ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。 
(2)ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。 
(3)ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
(4)ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务

从上面的源码我们知道,ThreadPoolExecutor类继承AbstractExecutorService类,看下AbstractExecutorService类的具体实现

public abstract class AbstractExecutorService implements ExecutorService {
	protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value {
    }
    protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
    }
    public Future<?> submit(Runnable task) {
    }
    public <T> Future<T> submit(Runnable task, T result) {
    }
    public <T> Future<T> submit(Callable<T> task) {
    }
    private <T> T doInvokeAny(Collection<? extends Callable<T>> tasks, boolean timed, long nanos) throws InterruptedException, ExecutionException, TimeoutException {
    };
    public <T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException {
    };
    public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
    };
    public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException {
    };
    public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException {
    };
}

AbstractExecutorService是一个抽象类,它实现了ExecutorService接口。
再来看看ExecutorService接口的实现

public interface ExecutorService extends Executor {
	void shutdown();
	List<Runnable> shutdownNow();
	boolean isShutdown();
	boolean isTerminated();
	boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;
	<T> Future<T> submit(Callable<T> task);
	<T> Future<T> submit(Runnable task, T result);
	Future<?> submit(Runnable task);
	<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException;
	<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException;
	<T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException;
	<T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;

而ExecutorService又是继承了Executor接口,我们看一下Executor接口的实现:

public interface Executor {
	void execute(Runnable command);
}

到这里,就可以看出这四者之间的关系,

Executor是一个顶层接口,在它里面只声明了一个方法execute(Runnable),返回值为void,参数为Runnable类型,从字面意思可以理解,就是用来执行传进去的任务的;

然后ExecutorService接口继承了Executor接口,并声明了一些方法:submit、invokeAll、invokeAny以及shutDown等;

抽象类AbstractExecutorService实现了ExecutorService接口,基本实现了ExecutorService中声明的所有方法;

然后ThreadPoolExecutor继承了类AbstractExecutorService。

下图可表示这种关系
在这里插入图片描述

二、线程池实现原理

1、线程池状态
	//该状态表示线程池能接受新任务
    private static final int RUNNING    = -1 << COUNT_BITS;
    //此状态不再接受新任务,但可继续执行队列中的任务
    private static final int SHUTDOWN   =  0 << COUNT_BITS;
    //此状态全面拒绝,并中断正在处理的任务
    private static final int STOP       =  1 << COUNT_BITS;
    //该状态表示所有任务已经被终止
    private static final int TIDYING    =  2 << COUNT_BITS;
    //所有工作线程已经销毁,任务缓存队列已经清空或执行结束
    private static final int TERMINATED =  3 << COUNT_BITS;
2、任务的执行

在ThreadPoolExecutor类中,最核心的任务提交方法是execute()方法,对其原理进行研究

    public void execute(Runnable command) {
    	//判断提交的任务command是否为null,若是null,则抛出空指针异常;
        if (command == null)
            throw new NullPointerException();
        int c = ctl.get();
        // 如果当前线程数少于核心线程数,直接添加一个 worker 执行任务,
        // 创建一个新的线程,并把当前任务 command 作为这个线程的第一个任务
        if (workerCountOf(c) < corePoolSize) {
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
        // 当前线程数大于等于核心线程数,要么刚刚 addWorker 失败
        // 如果线程池处于 RUNNING ,把这个任务添加到任务队列 workQueue 中
        if (isRunning(c) && workQueue.offer(command)) {
            int recheck = ctl.get();
            // 若线程池不处于 RUNNING ,则移除已经入队的这个任务,并且执行拒绝策略
            if (! isRunning(recheck) && remove(command))
                reject(command);
            // 若线程池还是 RUNNING ,且线程数为 0,则开启新的线程
            // 这块代码的真正意图:担心任务提交到队列中了,但是线程都关闭了
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
        // 若 workQueue 满,到该分支
        // 以 maximumPoolSize 为界创建新 worker,
        // 若失败,说明当前线程数已经达到 maximumPoolSize,执行拒绝策略
        else if (!addWorker(command, false))
            reject(command);
    }

这个过程可由下图表示
在这里插入图片描述

三、Executors静态工厂几种常用线程池

//创建固定容量大小的缓冲池
    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
 //创建容量为1的缓冲池   
    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
 //创建一个缓冲池,缓冲池容量大小为Integer.MAX_VALUE   
    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值