Java多线程线程池

31次阅读

共计 1171 个字符,预计需要花费 3 分钟才能阅读完成。

合理的使用线程池有三个好处:
1. 降低资源消耗。
2. 提高响应速度。
3. 提高线程的可管理性。

线程池的实现原理

先看流程图:

如果当前线程池中的线程数目小于 corePoolSize,则每来一个任务,就会创建一个线程去执行这个任务;如果当前线程池中的线程数 >=corePoolSize,则每来一个任务,会尝试将其添加到任务缓存队列当中,若添加成功,则该任务会等待空闲线程将其取出去执行;若任务缓存队列已满,则会尝试创建新的线程去执行这个任务;如果当前线程池中的线程数目达到 maximumPoolSize,则会采取任务拒绝策略进行处理。

看一下 excute 的源码:

public void execute(Runnable command) {if (command == null) // 空任务抛出异常
            throw new NullPointerException();
        int c = ctl.get();
        // 1. 如果工作线程数小于核心线程数,则添加新的线程
        if (workerCountOf(c) < corePoolSize) {if (addWorker(command, true))
                return; // 添加成功则返回
            c = ctl.get(); // 否则获取线程池状态}
        // 2.  工作线程数大于等于核心线程数,则将任务放入缓存任务队列
        // 与操作:如果线程池正在运行,而且成功将任务插入缓存任务队列两个条件
        // 都满足则进入条件语句内
        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); // 添加无初始任务的线程
        }
        // 3. 任务入队失败,说明任务缓存任务队列已满,尝试添加新的线程处理
        // 如果添加失败则以某种方式拒绝任务
        else if (!addWorker(command, false))
            reject(command);
    }

线程池创建线程时,会将线程封装成工作线程 Worker,Worker 在执行完任务后,还会循环获取工作队列里的任务来执行。可以从 Worker 类的 run()方法里看出这点:

public void run(){
    try{Runnable task = firstTask();
        firstTask() = null;
        while (task != null || (task = getTask()) != null){runTask(task);
            task = null ;
        }finally{workerDone(this);
        }
    }
}

正文完
 0