线程池介绍
(1)在没有采取线程池技术的时候,往往是一个任务一个线程的方式,这样将会创建数以万计的线程,使得操作系统频繁的进行线程上下文切换,增加系统的负载(线程的创建和消亡都是需要消耗系统资源的)
(2)线程池技术为了解决这个问题而产生,预先创造了若干数量的线程(Worker 线程),并且将线程的创建控制交给ThreadPool类,而不是客户端(客户端将任务job放入工作队列jobs后便返回)
线程池的实现
DefaultThreadPool主要负责workers 的封装与管理,并且提供addWorkers()、removeWorker()、shutdown()方法;及其增加job进工作队列的方法,execute(Job job)。
角色:
(1)jobs :工作队列(LinkedList),每一个job线程的run()负责执行任务;
(2)workers :工作者列表(ArrayList),每一个worker线程的run()负责不断地从工作队列上取出工作,然后执行;当工作队列中没有job任务时候,则等待阻塞,需要notify()或者notifyAll()唤醒
// 1. 抽象接口
public interface ThreadPool<Job extends Runnable> {
//执行一个Job,这个Job需要实现Runnable
void execute(Job job);
//关闭线程池
void shutdown();
//增加工作者线程
void addWorkers(int num);
//减少工作者线程
void removeWorker(int num);
//得到正在等待执行的任务数量
int getJobSize();
}
// 2. 默认实现
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
public class DefaultThreadPool<Job extends Runnable> implements ThreadPool<Job> {
// 线程池最大限制数
private static final int MAX_WORKEY_NUMBERS = 10;
// 线程池默认的数量
private static final int DEFAULT_WORKER_NUMBERS = 5;
// 线程池最小的数量
private static final int MIN_WORKEY_NUMBERS = 1;
// 这是一个工作列表,将会向里边插入工作
private final LinkedList<Job> jobs = new LinkedList<>();
// 工作者列表(ArrayList是非线程安全的)
private final List<Worker> workers = Collections.synchronizedList(new ArrayList<Worker>());
// 工作者线程的数量
private int workerNum = DEFAULT_WORKER_NUMBERS;
// 线程编号生成(加了synchronized的long)
private AtomicLong threadNum = new AtomicLong();
public DefaultThreadPool() {
initializeWorkers(DEFAULT_WORKER_NUMBERS);
}
public DefaultThreadPool(int num) {
workerNum = num > MAX_WORKEY_NUMBERS ? MAX_WORKEY_NUMBERS : num < MIN_WORKEY_NUMBERS ? MIN_WORKEY_NUMBERS : num;
initializeWorkers(workerNum);
}
private void initializeWorkers(int num) {
for(int i=0;i<num;i++) {
Worker worker = new Worker();
workers.add(worker);
Thread thread = new Thread(worker,"ThreadPool-Worker-"+threadNum.incrementAndGet());
thread.start();
}
}
// 增加一个job到队列尾部,然后唤醒一个工作者(确保有一个线程被唤醒即可,比notifyAll()开销小)
@Override
public void execute(Job job) {
if(job!=null) {
// 添加一个工作,然后进行通知
synchronized(jobs) {
jobs.add(job);
jobs.notify();
}
}
}
@Override
public void shutdown() {
for(Worker worker : workers) {
worker.shutdown();
}
}
@Override
public void addWorkers(int num) {
synchronized(jobs) {
// 限制新增的Worker数量不能超过最大值
if(num + this.workerNum > MAX_WORKEY_NUMBERS) {
num = MAX_WORKEY_NUMBERS - this.workerNum;
}
initializeWorkers(num);
this.workerNum += num;
}
}
@Override
public void removeWorker(int num) {
synchronized(jobs) {
if(num >= this.workerNum) {
throw new IllegalArgumentException("beyond workNum");
}
// 按照给定的数量停止Worker
int count = 0;
while(count < num) {
Worker worker = workers.get(count);
if(workers.remove(worker)) {
worker.shutdown();
count++;
}
}
this.workerNum -= count;
}
}
@Override
public int getJobSize() {
return jobs.size();
}
/****
* 工作者线程不断地从工作队列上取出工作,并且执行;
* 当工作队列中没有job任务时候,则等待阻塞,需要notify()或者notifyAll()唤醒
*/
class Worker implements Runnable {
// 是否工作
private volatile boolean running = true;
// 每个工作者线程负责从jobs队列中取出一个job执行任务
@Override
public void run() {
while(running) {
Job job = null;
synchronized (jobs) {
// 如果工作列表是空的,那么就wait
while(jobs.isEmpty()) {
try{
jobs.wait(); // 需要notify()或者notifyAll()唤醒
}catch(InterruptedException ex) {
// 感知到外部对WorkThread的中断操作,返回
Thread.currentThread().interrupt();
return;
}
}
// 取出一个Job
job = jobs.removeFirst();
}
if(jobs!=null) {
try{
job.run();
}catch(Exception ex) {
}
}
}
}
public void shutdown() {
running = false;
}
}
}
参考
《Java并发编程的艺术》