Java线程池源码分析

Java线程池的架构

Executor (接口)-> ExecutorService (接口)-> AbstractExecutorService (抽
象类) -> ThreadPoolExecutor (重点关注类)

其中Executors是工具类,可以看到newCachedThreadPool与newFixedThreadPool两个方法

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

其中线程池中的阻塞队列 : SynchronousQueue, LinkedBlockingQueue, ArrayBlockingQueue都有很大的差别 (后面会说到)

ExecutorService接口

public interface ExecutorService extends Executor {
		void shutdown(); //关闭线程池,已提交的任务继续执行,不接受继续提交新任务
		
		List<Runnable> shutdownNow(); //关闭线程池中所有的任务,已提交的任务也会强制终止

		boolean isShutdown();  //判断线程池是否关闭;Returns {@code true} if this executor has been shut down; 与shutdownNow()进行配合
		
		boolean isTerminated(); // @return {@code true} if all tasks have completed following shut down;与shutdown进行配合

		<T> Future<T> submit(Callable<T> task);	//提交一个Callable任务

ThreadPoolExecutor 重头戏

面试重点:队列是否有界?提交任务时队列满了怎么办?什么情况下会创建新的线程?提交任务时线程池满了怎么办?空闲线程怎么关掉
核心构造函数:
		1. corePoolSize 核心线程池 
		2. maximumPoolSize 最大线程池
		3. keepAliveTime 最大存活时间  <**空闲线程的保活时间,如果某线程的空闲时间超过这个值都没有任务给他做,则该线程就可以被关闭 !!!如果线程池中的线程数少于等于核心线程数 corePoolSize,那么这些线程不会因为空闲太长时间而被关闭**>
		4. 时间单位
		5. 阻塞队列
		6. 线程生产工厂
		7. 拒绝执行处理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;
    }

线程池中的各个状态:
RUNNING:最正常的状态:接受新的任务,处理等待队列中的任务
SHUTDOWN:不接受新的任务提交,但是会继续处理等待队列中的任务
STOP:不接受新任务提交,不再处理等待队列中的任务,中断正在执行任务的线程
TIDYING:所有的任务都销毁,workCount 为 0。线程池的状态在转换为 TIDYING 状态时,会执行钩子方法 terminated()
TERMINATED:terminated() 方法结束后,线程池的状态就会变成这个

public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        int c = ctl.get();
	
		//   当运行的线程数少于核心线程数。试图启动一个新的线程执行命令。调用addWorker并自动检查线程运行状态以及线程数,以阻止错误的线程被加
        if (workerCountOf(c) < corePoolSize) {
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
        当到了这里 ,表明 要么线程数大于等于核心线程数 ,要么addWorker失败
        if (isRunning(c) && workQueue.offer(command)) {
            int recheck = ctl.get();
            if (! isRunning(recheck) && remove(command))
                reject(command);
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
        //如果workQueeu队列已满,那么进入到这个分支
        //以maximumPoolSize为界创建新的worker
        else if (!addWorker(command, false))
            reject(command);
    }

关键点分析:
ThreadPoolExecutor线程池中维护了两个关键的数据结构

  1. HashSet《Worker》 workers 用于存储线程
  2. BlockingQueue《Runnable》 workQueue用于存储任务队列

问1:*HashSet能否保证多个线程同时添加到Set集合时,不会导致集合大小维护的不准确
答1: 内部使用了一个CAS控制集合大小。

问2: new ThreadPoolExecutor(10,20,3000,TimeUnit.millsecond,new ArrayBlockingQueue(50)),请判断其任务添加时,内部状态变化的过程
答2: 当核心线程数小于10时,添加的任务直接被线程工作了;当核心线程数超过10时,任务被添加到有界阻塞队列中;当有界队列被加满时,线程数继续添加直到添加到最大值;如果还是继续添加任务,将导致线程池执行RejectedPolicy。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值