在面试的时候,如果面试官问你:你在工作中单一的/固定数的/可变你的三种创建线程池的方法,你用哪个多?
答:一个都不用,我们都是自己手写的。因为阿里巴巴开发手册里面明确的提到: 线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式。
一:手写一个线程池采用AbortPolicy拒绝策略的代码如下:
package com.mszl.thread;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* 功能:手写一个线程池
* 备注:更多资料请访问 http://www.91mszl.com
* @author bobo teacher
*/
public class ThreadPoolDiyDemo {
public static void main(String[] args) {
// int corePoolSize:2
// int maximumPoolSize:5
// long keepAliveTime, 1
// TimeUnit unit,
// BlockingQueue workQueue:3
// ThreadFactory threadFactory,
// RejectedExecutionHandler handler
ExecutorService threadPool=new ThreadPoolExecutor(2, 5,
1, TimeUnit.SECONDS,
new LinkedBlockingQueue(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
// 模拟10个用户到银行的5个窗口去取钱
try{
for(int i=1; i<=7; i++){
threadPool.execute(new Runnable() {
public void run() {
System.out.println(Thread.currentThread().getName() + "\t" + "办理完成");
}
});
}
} catch(Exception ex){
ex.printStackTrace();
} finally{
threadPool.shutdown(); // 关闭线程池
}
}
}
当模拟7个用户取钱时执行结果为:
pool-1-thread-1 办理完成
pool-1-thread-1 办理完成
pool-1-thread-1 办理完成
pool-1-thread-1 办理完成
pool-1-thread-2 办理完成
pool-1-thread-3 办理完成
pool-1-thread-4 办理完成
当模拟9个用户取钱时执行结果为:
pool-1-thread-1 办理完成
pool-1-thread-3 办理完成
pool-1-thread-2 办理完成
pool-1-thread-1 办理完成
pool-1-thread-5 办理完成
pool-1-thread-3 办理完成
pool-1-thread-4 办理完成
pool-1-thread-1 办理完成
java.util.concurrent.RejectedExecutionException: Task com.mszl.thread.ThreadPoolDiyDemo$1@1f96302 rejected from java.util.concurrent.ThreadPoolExecutor@14eac69[Running, pool size = 5, active threads = 0, queued tasks = 0, completed tasks = 8]
at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2047)
at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:823)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1369)
at com.mszl.thread.ThreadPoolDiyDemo.main(ThreadPoolDiyDemo.java:37)
分析:因为我们模拟的是9个用户大于了8个(最大线程数5+队列数3=8),并且我们采用的是默认的AbortPolicy拒绝策略,根据AbortPolicy的特性,直接抛异常。
二:手写一个线程池采用 CallerRunPolicy拒绝策略的代码如下:
package com.mszl.thread;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* 功能:手写一个线程池
* 备注:更多资料请访问 http://www.91mszl.com
* @author bobo teacher
*/
public class ThreadPoolDiyDemo {
public static void main(String[] args) {
// int corePoolSize:2
// int maximumPoolSize:5
// long keepAliveTime, 1
// TimeUnit unit,
// BlockingQueue workQueue:3
// ThreadFactory threadFactory,
// RejectedExecutionHandler handler
ExecutorService threadPool=new ThreadPoolExecutor(2, 5,
1, TimeUnit.SECONDS,
new LinkedBlockingQueue(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.CallerRunsPolicy());
// 模拟10个用户到银行的5个窗口去取钱
try{
for(int i=1; i<=9; i++){
threadPool.execute(new Runnable() {
public void run() {
System.out.println(Thread.currentThread().getName() + "\t" + "办理完成");
}
});
}
} catch(Exception ex){
ex.printStackTrace();
} finally{
threadPool.shutdown(); // 关闭线程池
}
}
}
执行结果:
pool-1-thread-2 办理完成
pool-1-thread-4 办理完成
pool-1-thread-2 办理完成
pool-1-thread-3 办理完成
pool-1-thread-1 办理完成
pool-1-thread-5 办理完成
pool-1-thread-2 办理完成
pool-1-thread-4 办理完成
main 办理完成
分析:我们模拟的是9个用户大于了8个(最大线程数5+队列数3=8),并且我们采用的是CallerRunPolicy 拒绝策略,根据CallerRunPolicy 的特性,该策略既不会抛弃任务,也不会抛出异常,而是将某些任务回退到调用者,从而降低新任务的流量。所以有一个线程退回到了main线程。
三:手写一个线程池采用 DiscardOldestPolicy 拒绝策略的代码如下:
package com.mszl.thread;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* 功能:手写一个线程池
* 备注:更多资料请访问 http://www.91mszl.com
* @author bobo teacher
*/
public class ThreadPoolDiyDemo {
public static void main(String[] args) {
// int corePoolSize:2
// int maximumPoolSize:5
// long keepAliveTime, 1
// TimeUnit unit,
// BlockingQueue workQueue:3
// ThreadFactory threadFactory,
// RejectedExecutionHandler handler
ExecutorService threadPool=new ThreadPoolExecutor(2, 5,
1, TimeUnit.SECONDS,
new LinkedBlockingQueue(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.DiscardOldestPolicy());
// 模拟10个用户到银行的5个窗口去取钱
try{
for(int i=1; i<=9; i++){
threadPool.execute(new Runnable() {
public void run() {
System.out.println(Thread.currentThread().getName() + "\t" + "办理完成");
}
});
}
} catch(Exception ex){
ex.printStackTrace();
} finally{
threadPool.shutdown(); // 关闭线程池
}
}
}
执行结果:
pool-1-thread-2 办理完成
pool-1-thread-1 办理完成
pool-1-thread-2 办理完成
pool-1-thread-3 办理完成
pool-1-thread-4 办理完成
pool-1-thread-2 办理完成
pool-1-thread-1 办理完成
pool-1-thread-5 办理完成
分析:我们模拟的是9个用户大于了8个(最大线程数5+队列数3=8),并且我们采用的是 DiscardOldestPolicy 拒绝策略,根据 DiscardOldestPolicy 的特性,抛弃队列中等待最久的任务,然后把当前任务加入队列中尝试再次提交当前任务。所以只有8个办理完成,还有一个被抛弃了。
四:手写一个线程池采用 DiscardPolicy 拒绝策略的代码如下:
package com.mszl.thread;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* 功能:手写一个线程池
* 备注:更多资料请访问 http://www.91mszl.com
* @author bobo teacher
*/
public class ThreadPoolDiyDemo {
public static void main(String[] args) {
// int corePoolSize:2
// int maximumPoolSize:5
// long keepAliveTime, 1
// TimeUnit unit,
// BlockingQueue workQueue:3
// ThreadFactory threadFactory,
// RejectedExecutionHandler handler
ExecutorService threadPool=new ThreadPoolExecutor(2, 5,
1, TimeUnit.SECONDS,
new LinkedBlockingQueue(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.DiscardPolicy());
// 模拟10个用户到银行的5个窗口去取钱
try{
for(int i=1; i<=9; i++){
threadPool.execute(new Runnable() {
public void run() {
System.out.println(Thread.currentThread().getName() + "\t" + "办理完成");
}
});
}
} catch(Exception ex){
ex.printStackTrace();
} finally{
threadPool.shutdown(); // 关闭线程池
}
}
}
执行结果:
pool-1-thread-2 办理完成
pool-1-thread-2 办理完成
pool-1-thread-5 办理完成
pool-1-thread-4 办理完成
pool-1-thread-3 办理完成
pool-1-thread-1 办理完成
pool-1-thread-5 办理完成
pool-1-thread-2 办理完成
分析:我们模拟的是9个用户大于了8个(最大线程数5+队列数3=8),并且我们采用的是 DiscardPolicy 拒绝策略,根据 DiscardPolicy 的特性,直接丢弃任务,不予任何处理也不抛出异常。