1.有界队列的使用
public class MyTask implements Runnable {
private int taskId;
private String taskName;
public MyTask(int taskId, String taskName) {
this.taskId = taskId;
this.taskName = taskName;
}
@Override
public void run() {
try {
System.out.println("run taskId=" + taskId);
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public int getTaskId() {
return taskId;
}
public void setTaskId(int taskId) {
this.taskId = taskId;
}
public String getTaskName() {
return taskName;
}
public void setTaskName(String taskName) {
this.taskName = taskName;
}
@Override
public String toString() {
return Integer.toString(taskId);
}
}
import java.util.concurrent.*;
public class UseThreadPoolExecutor1 {
public static void main(String[] args) {
ThreadPoolExecutor pool = new ThreadPoolExecutor(
1,
2,
60,
TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(3)
);
MyTask mt1 = new MyTask(1, "任务1");
MyTask mt2 = new MyTask(2, "任务2");
MyTask mt3 = new MyTask(3, "任务3");
MyTask mt4 = new MyTask(4, "任务4");
MyTask mt5 = new MyTask(5, "任务5");
MyTask mt6 = new MyTask(6, "任务6");
pool.execute(mt1);
pool.execute(mt2);
pool.execute(mt3);
pool.execute(mt4);
pool.execute(mt5);
pool.execute(mt6);
pool.shutdown();
}
}
线程池提交的时候,分别试验,提交1个,提交2个,提交3个,提交5个,提交6个。
2.无界队列的使用
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
public class UseThreadPoolExecutor2 implements Runnable {
private static AtomicInteger count = new AtomicInteger(0);
@Override
public void run() {
try {
int temp = count.incrementAndGet();
System.out.println("任务" + temp);
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws InterruptedException {
BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
// BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(10);
ExecutorService pool = new ThreadPoolExecutor(
5,
10,
120L,
TimeUnit.SECONDS,
queue);
for (int i = 0; i < 20; i++) {
pool.execute(new UseThreadPoolExecutor2());
}
Thread.sleep(1000);
System.out.println("queue size: " + queue.size());
Thread.sleep(2000);
}
}
使用无界队列时,maxPoolSize就不生效了。
3.拒绝策略
AbortPolicy: 抛出一个异常,系统可以继续正常运行(jdk默认的拒绝策略)
DiscardOldestPolicy,看一个例子
public class UseThreadPoolExecutor1 {
public static void main(String[] args) {
ThreadPoolExecutor pool = new ThreadPoolExecutor(
1,
2,
60,
TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(3),
new ThreadPoolExecutor.DiscardOldestPolicy()
);
MyTask mt1 = new MyTask(1, "任务1");
MyTask mt2 = new MyTask(2, "任务2");
MyTask mt3 = new MyTask(3, "任务3");
MyTask mt4 = new MyTask(4, "任务4");
MyTask mt5 = new MyTask(5, "任务5");
MyTask mt6 = new MyTask(6, "任务6");
pool.execute(mt1);
pool.execute(mt2);
pool.execute(mt3);
pool.execute(mt4);
pool.execute(mt5);
pool.execute(mt6);
pool.shutdown();
}
}
第2个任务被丢掉了。
我们来推演一下。第1个任务提交之后,唯一的核心线程进行处理。第2、3、4个线程进入有界队列。第5个任务提交的时候,队列满,创建新的线程,此时达到了maxPoolSize。第6个线程提交的时候,2号线程是队列中最老线程,丢弃。然后6号线程重新提交,入队列。
自定义拒绝策略
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
public class MyReject implements RejectedExecutionHandler {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
System.out.println("自定义处理...");
System.out.println("当前被拒绝任务为:" + r.toString());
//在实际的业务场景中,可以用以下方式
//1.用http传json的方式,发送给数据源服务器,告诉它这个任务被拒绝了,下次可以重发。
//2.记录日志,暂缓到一个地方,之后,再跑一个定时的job,把这些没处理的任务再处理一遍。
//3.不管成功与否,都记录一下日志
//真实的工作中,一般都是先记录日志,稍后再去处理
}
}
import java.util.concurrent.*;
public class UseThreadPoolExecutor1 {
public static void main(String[] args) {
ThreadPoolExecutor pool = new ThreadPoolExecutor(
1,
2,
60,
TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(3),
new MyReject()
);
MyTask mt1 = new MyTask(1, "任务1");
MyTask mt2 = new MyTask(2, "任务2");
MyTask mt3 = new MyTask(3, "任务3");
MyTask mt4 = new MyTask(4, "任务4");
MyTask mt5 = new MyTask(5, "任务5");
MyTask mt6 = new MyTask(6, "任务6");
pool.execute(mt1);
pool.execute(mt2);
pool.execute(mt3);
pool.execute(mt4);
pool.execute(mt5);
pool.execute(mt6);
pool.shutdown();
}
}