第四章 线程池入门
- 阻塞线程的线程的特点是:该线程放弃cpu的使用,暂停运行,只有等到导致阻塞的原因消除之后才能运行。或者是被其他的线程中断,该线程也会推出阻塞状态。阻塞的原因有多种:大致分为三种来讨论,线程的阻塞,socket客户端的阻塞,socket服务器端的阻塞。
- 线程池的目的是提高服务器的响应能力。
4.1.1 创建线程池
public static void main(String[] args) {
LinkedBlockingDeque<Runnable> bq = new LinkedBlockingDeque<>(5);
ThreadPoolExecutor pool = new ThreadPoolExecutor(3, 8, 2000, TimeUnit.MILLISECONDS, bq);
for (int i=0;i<14;i++){
pool.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getId()+" is running...");
try {
Thread.sleep(800);
}catch (Exception e){}
}
});
}
pool.shutdown();
}
- 先启动核心线程,然后使用阻塞队列,最后新增线程。顺序
- 线程池中的线程数最大为8,当所有的任务都运行完成后,非核心线程数会在2秒后释放。
4.2 Executor接口
- executor接口中,只有一个executor方法,它表明在将来某个时刻,执行一个给定的任务。这个任务可以在一个新线程中或线程池中执行,也可以在调用executor方法的这个线程中执行。执行时间
- 执行器executor把任务的提交和任务的运行进行了有机分解,从而实现了解耦。通常无须显示创建线程。
4.3 ExecutorService接口
- executor接口只提供了任务的执行方法,为了解决执行服务对象的生命周期问题,executorService添加了一些用于生命周期管理的方法,如终止任务,提交任务,跟踪任务返回结果等。
- executorservice认为服务对象的生命周期有3种状态:运行,关闭和终止。
4.3.1 callable返回任务执行结果
static class MyTask implements Callable<String>{
private int id;
public MyTask(int id){
this.id = id;
}
public String call() throws Exception{
String result = "线程"+Thread.currentThread().getId()+",id="+id;
return result;
}
}
public static void main(String[] args) {
ExecutorService pool = new ThreadPoolExecutor(3,8,2000,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>(5));
List<Future<String>> results = new ArrayList<>();
for (int i=0;i<10;i++){
Future<String> f = pool.submit(new MyTask(i));
results.add(f);
System.out.println("任务:"+i+"完成");
}
pool.shutdown();
for (Future<String> f : results) {
try {
System.out.println(f.get());
Thread.sleep(800);
}catch (Exception e){}
}
}
4.4 Executors工具箱
4.4.1 newCachedThreadPool
- 当需要处理大量的短时任务时,这个线程池未对任务数量做约束,而且使用synchronousQueue减少入队与出队时间,就是为了快速满足高并发请求,即大量的并发请求无须等待,即可获得服务器的线程处理。
4.4.2 newFixedThreadPool
- 阻塞队列非常大,Integer.MAX_VALUE,当任务数量大于核心线程数时,都会被装入队列中,充分的空间容纳待执行的任务。
4.4.3 newSingleThreadExecutor
- 日志服务。固定线程数为1.
- 好处是:业务行为与写日志完全分离开来,不会因为文件的i/o影响业务操作的并发性能。
4.4.4 newScheduledThreadPool
- 提供了各种延时任务和定时任务的执行,并返回可用于取消或检查执行任务的对象。
4.4.5 newWorkStealingPool
- 任务分解执行,然后把执行结果合并的线程池。
- forkjoinpool的优势在于,可以充分利用多处理器的优势,把一个任务拆分成多个比较小的任务,把这些小任务负载到多个处理器上并行执行。当这些小任务执行完成后,再将这些执行结果合并起来。
4.5 线程工厂与线程池
4.5.1线程组
4.5.2 线程与线程组
- 新创建的线程默认使用创建者的线程组。
4.5.5 线程池与线程工厂