线程池原理
启动多个线程, 让他们永远处于运行状态, 有任务时就处理任务, 没有任务就等待.
各角色说明
任务发布者: 负责发布任务
包工头: 负责召集工人, 并让他们开始工作
工人: 负责处理任务
中间人: 负责协调任务, 将发布者和工人隔离开来
任务发布者和工人不直接打交道, 任务发布者把任务交给中间人后就不管了.
工人从中间人那里获取任务, 并处理, 没有任务时就等待.
示例代码
Main.java
public static void main(String[] args) {
// 设定中间人最多能承接的任务数量
Channel channel = new Channel(50);
// 设定包工头招工的数量
Employee employee = new Employee(channel, 3);
// 让工人开始工作
employee.start();
// 发布任务
for (int i=0; i<200; i++) {
Request request = new Request("任务" + i);
channel.putRequest(request);
}
}
中间人
import java.util.LinkedList;
import java.util.Queue;
/**
* 生产者和消费者中间的餐桌
*/
public class Channel {
// 任务队列
private final Queue<Request> queue;
// 最多任务数量
private final int maxRequestCount;
public Channel(int count) {
queue = new LinkedList<>();
this.maxRequestCount = count;
}
/**
* 新增任务
* @param request
*/
public synchronized void putRequest(Request request) {
while (queue.size() == maxRequestCount) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
queue.add(request);
notifyAll();
}
/**
* 处理任务
* @return
*/
public synchronized Request takeRequest() {
while (queue.size() == 0) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Request request = queue.poll();
notifyAll();
return request;
}
public int getSize() {
return queue.size();
}
}
包工头
/**
* 包工头, 负责招人并工作
*/
public class Employee {
private final Channel channel;
// 工人数量
private final int workerNum;
public Employee(Channel channel, int num) {
this.channel = channel;
this.workerNum = num;
}
public void start() {
for (int i=0; i<workerNum; i++) {
WorkerThread workerThread = new WorkerThread(channel);
workerThread.start();
}
}
}
工人
/**
* 工人
* 一旦进入工作状态, 就永不停止
*/
public class WorkerThread extends Thread {
private final Channel channel;
public WorkerThread(Channel channel) {
this.channel = channel;
}
public void run() {
while (true) {
Request request = channel.takeRequest();
request.execute();
}
}
}
具体任务
/**
* 需要处理的请求
*/
public class Request {
private final String content;
public Request(String content) {
this.content = content;
}
public void execute() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ": " + content);
}
}