20.custom自定义线程池
自定义线程池
1.若Executors工厂类无法满足需求,可以自己使用工厂类创建线程池,底层都是使用了ThreadPoolExecutor这个类可以自定义。
public ThreadPoolExecutor(int corePoolSize(当前核心线程数),
int maximunPoolSize(最大线程数),
long keepAliveTime(保持活跃时间),
TimeUnit utin(时间单位),
BlockingQueue<Runnable> workQueue(线程队列容器),
ThreadFactory threadFactory(线程工厂),
RejectedExecutionHandler rejectedExecutionHandler(拒绝执行的方法,线程队列阻塞到容器等待、例:限制最大执行、));
2.有界队列【ArrayBlockingQueue】,若有新的任务则立即去执行:若有新的线程需要执行,目标线程池实际数小于"coreRoolSize",则优先参加线程,若大于,
则会将任务加入队 列中,若队列已经满,则在总线程数不大于maximumPoolSize(最大coreRoolSize数)的前提下。创建一个新的线程,若大于 maximumPoolSize则实行拒绝策略、或其他处理方式。
3.无界队列【LinkedBlockingQueue】与有界队列对比:除非资源耗尽,否则无界队列在加入任务不存在失败的情况下,当有新的任务到来,系统的线程数小于
corePoolSize的时候,则新建线程去执行任务队列,,达到maxCorePoolsize后就不会增加了,若后续还有任务到来,而且没有空闲的资源,则把任务进行
队列中去等待。若创建任务与处理任务的速度差异很大,无界队列保持快速增加等待的任务空间,一直到资源耗尽。
4.拒绝策略
Abortlicy:直接抛出异常、核心系统则不会受到影响。
CallerRunspPolicy:该策略直接在调用者现场,运行当前被拒绝的任务、丢弃的任务(我刚刚进行队列就满了,那么就让我插个队执行)。
DiscardOldestPolicy:丢弃最老的一个请求(被阻塞在队列中很长时间),尝试直接运行当前被拒绝的任务。
DiscardPolicy:丢弃无法处理的任务,被给与任何的后续处理。
5.自定义策略
implements RejectedExecutionHandle
案例1:有界队列
package demo8.threadPool;
import java.util.concurrent.*;
public class CustomThreadPool1 {
/* 有界队列ArrayBlockingQueue:
若有新的线程需要执行,日光线程池实际数小于"coreRoolSize",则优先参加线程,若大于,则会将任务加入队列中,若队列已经满,则在总线程
数不大于maximumPoolSize(最大coreRoolSize数)的前提下。创建一个新的线程,若大于maximumPoolSize则实行拒绝策略、或其他处理方式。*/
public static void main(String[] args) {
BlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<Runnable>(3);
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1,
2,
60,
TimeUnit.SECONDS,
blockingQueue);
UserTask userTask1 = new UserTask(1, "任务-1");
UserTask userTask2 = new UserTask(2, "任务-2");
UserTask userTask3 = new UserTask(3, "任务-3");
UserTask userTask4 = new UserTask(4, "任务-4");
UserTask userTask5 = new UserTask(5, "任务-5");
threadPoolExecutor.execute(userTask1);
threadPoolExecutor.execute(userTask2);
threadPoolExecutor.execute(userTask3);
threadPoolExecutor.execute(userTask4);
threadPoolExecutor.execute(userTask5);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
threadPoolExecutor.shutdown();
}
}
输出:
pool-1-thread-1 run taskId:1 pool-1-thread-2 run taskId:5 pool-1-thread-2 run taskId:3 pool-1-thread-1 run taskId:2 pool-1-thread-2 run taskId:4
这种情况处理完所有的任务
package demo8.threadPool;
/**
* Created by liudan on 2017/7/23.
*/
public class UserTask implements Runnable {
private int id;
private String taskName;
@Override
public void run() {
try {
Thread.sleep(1000);
System.err.println(Thread.currentThread().getName()+"\t run taskId:"+this.getId());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public UserTask() {
}
public UserTask(int id, String taskName) {
this.id = id;
this.taskName = taskName;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTaskName() {
return taskName;
}
public void setTaskName(String taskName) {
this.taskName = taskName;
}
@Override
public String toString() {
return "UserTask{" +
"id=" + id +
'}';
}
}
public static void main(String[] args) {
BlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<Runnable>(3);
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1,
2,
60,
TimeUnit.SECONDS,
blockingQueue);
UserTask userTask1 = new UserTask(1, "任务-1");
UserTask userTask2 = new UserTask(2, "任务-2");
UserTask userTask3 = new UserTask(3, "任务-3");
UserTask userTask4 = new UserTask(4, "任务-4");
UserTask userTask5 = new UserTask(5, "任务-5");
UserTask userTask6 = new UserTask(6, "任务-6");多加一个
threadPoolExecutor.execute(userTask1);
threadPoolExecutor.execute(userTask2);
threadPoolExecutor.execute(userTask3);
threadPoolExecutor.execute(userTask4);
threadPoolExecutor.execute(userTask5);
threadPoolExecutor.execute(userTask6);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
threadPoolExecutor.shutdown();
}
输出:
Exception in thread "main" java.util.concurrent.RejectedExecutionException:
Task UserTask{id=6} rejected from java.util.concurrent.ThreadPoolExecutor@6f94fa3e
[Running, pool size = 2, active threads = 2, queued tasks = 3, completed tasks = 0] 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 demo8.threadPool.CustomThreadPool1.main(CustomThreadPool1.java:35) pool-1-thread-1 run taskId:1 pool-1-thread-2 run taskId:5 pool-1-thread-1 run taskId:2 pool-1-thread-2 run taskId:3 pool-1-thread-1 run taskId:4
案例3:自定义拒绝策略
package demo8.threadPool;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
public class CustomDiscardPolicy implements RejectedExecutionHandler {
public CustomDiscardPolicy() {
}
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
System.err.println("拒绝任务");
/**
* 用日志记录保存下,可做后续的扩展操作
*/
System.err.println("加入任务log...\t"+r.toString());
}
}
public static void main(String[] args) {
BlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<Runnable>(3);
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1,
2,
60,
TimeUnit.SECONDS,
blockingQueue,
new CustomDiscardPolicy());//使用自定义拒绝策略
UserTask userTask1 = new UserTask(1, "任务-1");
UserTask userTask2 = new UserTask(2, "任务-2");
UserTask userTask3 = new UserTask(3, "任务-3");
UserTask userTask4 = new UserTask(4, "任务-4");
UserTask userTask5 = new UserTask(5, "任务-5");
UserTask userTask6 = new UserTask(6, "任务-6");
threadPoolExecutor.execute(userTask1);
threadPoolExecutor.execute(userTask2);
threadPoolExecutor.execute(userTask3);
threadPoolExecutor.execute(userTask4);
threadPoolExecutor.execute(userTask5);
threadPoolExecutor.execute(userTask6);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
threadPoolExecutor.shutdown();
}
输出:
拒绝任务 加入任务log... UserTask{id=6} pool-1-thread-1 run taskId:1 pool-1-thread-2 run taskId:5 pool-1-thread-1 run taskId:2 pool-1-thread-2 run taskId:3 pool-1-thread-1 run taskId:4
案例4:无界队列LinkedBlockingQueue
package demo8.threadPool;
import java.util.concurrent.*;
public class CustomThreadPool2 {
/* 无界队列LinkedBlockingQueue:
与有界队列相比,除非系统资源耗尽,否则无界的任务队列不存在加入任务队列失败的情况下,当有新的任务到来,系统的线程数小于coreRoolSize
时候,则新建线程执行任务,当到达coreRoolSize后就不会增加了,若后续还有新的任务加入,而且没有空闲的线程资源,则任务直接进入队列等待
。若任务创建和处理速度差异很大,无界队列保持快速增长,知道耗尽系统内存。*/
public static void main(String[] args) throws InterruptedException {
BlockingQueue<Runnable> blockingQueue = new LinkedBlockingQueue<Runnable>();
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5,10,120L, TimeUnit.SECONDS,blockingQueue);
//ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(4);
for (int i=1;i<=20;i++){
threadPoolExecutor.execute(new UserTask(i,"任务-"+i));
}
Thread.sleep(1000);
System.err.println("blockingQueue size:"+blockingQueue.size());
Thread.sleep(2000);
}
}
输出:
pool-1-thread-1 run taskId:1 pool-1-thread-2 run taskId:2 pool-1-thread-3 run taskId:3 pool-1-thread-4 run taskId:4 pool-1-thread-5 run taskId:5 blockingQueue size:10 pool-1-thread-2 run taskId:7 pool-1-thread-4 run taskId:9 pool-1-thread-3 run taskId:8 pool-1-thread-1 run taskId:6 pool-1-thread-5 run taskId:10 pool-1-thread-2 run taskId:11 pool-1-thread-1 run taskId:14 pool-1-thread-3 run taskId:13 pool-1-thread-4 run taskId:12 pool-1-thread-5 run taskId:15 pool-1-thread-1 run taskId:17 pool-1-thread-4 run taskId:19 pool-1-thread-5 run taskId:20 pool-1-thread-2 run taskId:16 pool-1-thread-3 run taskId:18