学线程池需要了解
Executor
ExecutorService: submit()//异步方法
future :get()
FutureTask (常用)
FutureTask<Integer> task =new FutureTask<Integer>(new Callable(){
@Override
public Object call() throws Exception {
TimeUnit.MILLISECONDS.sleep(500);
return 1000;
}
});
new Thread(task).start();
System.out.println(task.get());
}
CompletableFuture 管理多个Future的结果 等功能
线程池
1、ThreadPoolExecutor
多个线程使用同一个队列
线程池自定义方法
ThreadPoolExecutor tpe = new ThreadPoolExecutor(2, 4, 60, TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(4),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.DiscardOldestPolicy());
7个参数
corePoolSize:核心线程池的线程数量
maximumPoolSize:最大的线程池线程数量
keepAliveTime:线程活动保持时间,线程池的工作线程空闲后,保持存活的时间。
unit:线程活动保持时间的单位。
workQueue:指定任务队列所使用的队列
threadFactory :线程工厂
RejectStrategy:指定拒绝策略
线程池流程
非核心线程如果keepAliveTime没有使用,就会归还给系统
拒绝策略jdk提供了四种策略(建议自定义策略)
Abort:抛异常
Discard:扔掉,不抛异常
DiscardOldest:扔掉排队时间最久的
callerRuns:调用者处理任务
自定义策略
class MyHandler implements RejectedExecutionHandler{
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
//伪码
//log("r rejected")
//save r kafka\mysql\redis
// ...
}
jdk提供的默认线程池(不建议使用)
1、SingleThreadExecutor
new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>())
为什么要有单线程的线程池?
任务队列,完整生命周期,为了方便管理。
2、CachedThreadPool
new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
SynchronousQueue() 必须有一个线程拿走,不然就阻塞
所以CachedThreadPool就是来一个线程,如果线程池没有线程,就创建一个线程。
3、FixedThreadPool
new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
自定义核心线程数量。
4、ScheduledThreadPoolExecutor 定时任务线程池
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue())
DelayedWorkQueue 定时任务
2、ForkJoinPool
每一个线程都有一个自己的队列
WorkStealingPool 每一个线程都有一个自己的队列,如果一个线程没有任务了,就可以去其他线程偷任务来执行。