1.定义线程池接口
/**
* 线程池接口,用于对线程进行管理
* 1.执行一个任务
* 2.关闭线程池
* 3.增加线程池中线程的数量
* 4.减少线程池中线程的数量
**/
public interface ThreadPool<Job extends Callable> {
/**
* 将任务放入到线程池中进行执行
* @param job 继承了callable的任务
* @return
*/
boolean execute(Job job);
/**
* 关闭线程池
* @return
*/
boolean shutdown();
/**
* 增加线程池中工作的线程的数量
* @param num 需要增加的数量
* @return
*/
boolean addWorkers(int num);
/**
* 减少线程池中工作的线程的数量
* @param num 需要减少的数量
* @return
*/
boolean removeWorkers(int num);
}
2.默认实现线程池
/**
* 线程池接口的默认实现
**/
public class DefaultThreadPool<Job extends Callable> implements ThreadPool<Job> {
/**
* 最大工作线程的数量
*/
private static final int MAX_WORKER_NUMBERS = 10;
/**
* 默认的工作线程的数量
*/
private static final int DEFAULT_WORKER_NUMBERS = 5;
/**
* 最小工作线程的数量
*/
private static final int MIN_WORKER_NUMBERS = 1;
/**
* 任务线程队列
*/
private LinkedList<Job> jobs = new LinkedList<>();
/**
* 工作线程队列,由于要进行增删操作,所以要使用线程安全的队列
*/
private List<Worker> workers = Collections.synchronizedList(new ArrayList<>());
private AtomicLong threadMarker = new AtomicLong(0);
public DefaultThreadPool() {
initWorkers(DEFAULT_WORKER_NUMBERS);
}
/**
* 构造函数
* @param workerNum 工作线程的数量,最大10个,最小1个
*/
public DefaultThreadPool(int workerNum) {
int num = workerNum > MAX_WORKER_NUMBERS ? MAX_WORKER_NUMBERS : workerNum;
num = num < MIN_WORKER_NUMBERS ? MIN_WORKER_NUMBERS : num;
initWorkers(num);
}
/**
* 初始化工作线程
* @param num 工作线程的数量
*/
private void initWorkers(int num) {
for(int i = 0; i < num; i++) {
createWorker();
}
}
/**
* 将任务放入到线程池中进行执行
*
* @param job 继承了callable的任务
* @return
*/
@Override
public boolean execute(Job job) {
synchronized (jobs) {
// 添加一个任务到任务队列尾部,并将一个工作线程唤醒
jobs.addLast(job);
// 不需要使用notifyAll,因为此次只是添加一个任务,只需要唤醒一个工作线程就可以了
jobs.notify();
}
return true;
}
/**
* 关闭线程池
*
* @return
*/
@Override
public boolean shutdown() {
for (Worker worker : workers) {
worker.shutdown();
}
synchronized (jobs) {
jobs.notifyAll();
}
return true;
}
/**
* 增加线程池中工作的线程的数量
*
* @param num 需要增加的数量
* @return
*/
@Override
public boolean addWorkers(int num) {
num = num < 1 ? 0 : num;
int addNum = num + workers.size() > MAX_WORKER_NUMBERS ? MAX_WORKER_NUMBERS - workers.size() : num;
if(addNum > 0) {
for(int i = 0; i < addNum; i++) {
createWorker();
}
}
return true;
}
/**
* 减少线程池中工作的线程的数量
*
* @param num 需要减少的数量
* @return
*/
@Override
public boolean removeWorkers(int num) {
int removeNum = num > workers.size() ? workers.size() : num;
removeNum = workers.size() - removeNum < MIN_WORKER_NUMBERS ? workers.size() - MIN_WORKER_NUMBERS : removeNum;
for(int i = 0; i < removeNum; i++) {
Worker worker = workers.get(i);
workers.remove(worker);
worker.shutdown();
}
synchronized (jobs) {
jobs.notifyAll();
}
return true;
}
/**
* 创建一个工作线程,并且将工作线程放入到队列中管理,并启动工作线程
*/
private void createWorker() {
Worker worker = new Worker();
workers.add(worker);
Thread thread = new Thread(worker, "WorkerThread-Pool-" + threadMarker.incrementAndGet());
thread.start();
}
/**
* 工作线程
*/
class Worker implements Runnable {
private final Logger logger = LoggerFactory.getLogger(Worker.class);
private volatile boolean running = true;
@Override
public void run() {
logger.info("{}启动成功", Thread.currentThread().getName());
while (running) {
Job job = null;
synchronized (jobs) {
// 如果任务队列为空,则将工作线程挂起,并且释放锁,工作线程从runnable状态变成waiting状态,进入到等待队列中,
// waiting状态等待其他线程唤醒后,从等待队列进入到阻塞队列,然后重新获取锁,然后解除waiting状态,进入runnable状态
while (running && jobs.isEmpty()) {
try {
logger.info("{}等待任务...", Thread.currentThread().getName());
jobs.wait();
} catch (InterruptedException e) {
// 如果该线程被外部线程打断,打断该线程,并且设置running=false优雅的推出线程
logger.info("{}等待被打断...", Thread.currentThread().getName());
Thread.currentThread().interrupt();
running = false;
}
}
if(!jobs.isEmpty()) {
logger.info("{}获取一个任务", Thread.currentThread().getName());
job = jobs.removeFirst();
}
}
if(Objects.nonNull(job)) {
try {
logger.info("{}正在执行一个任务", Thread.currentThread().getName());
job.call();
logger.info("{}执行完成一个任务", Thread.currentThread().getName());
} catch (Exception e) {
// 忽略本次执行的异常,不然就会出现一次任务线程影响当前工作线程的情况
}
}
}
}
/**
* 优雅的关闭线程
* 将running设置成false,等待工作线程执行完当前任务,就不再执行新的任务,然后退出线程
*/
public void shutdown() {
running = false;
}
}
}
3.待实现...
根据一定的设计模式,配置化管理,参数化设计,功能设计等等,可以极大的扩展线程池的功能