思考?
1 为什么要使用执行器和线程池?
2 执行器和线程是什么?怎么使用
执行器
线程执行器分离了任务的创建和执行,提高了线程的性能
线程池
避免了频繁地创建和销毁线程,达到线程对象的重用,可以根据项目灵活地控制并发的数量
ExecutorService (java.util.concurrent)
1 Executors.newCachedThreadPool() 可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程
2 Executors.newFixedThreadPool() 定长线程池,可控制线程最大并发数,超出的线程会在队列中等待
3 Executors.newScheduledThreadPool() 定长线程池,支持定时及周期性任务执行
4 Executors.newSingleThreadExecutor() 单线程的线程池,只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO,LIFO,优先级)执行
执行方法submit和execute的区别
1 接收的参数不一样 submit参数是Callable, execute参数是Runnable
2 submit存在返回值,可以知道线程的执行结果,例如:2.1
2.1 Future future = excutorService.submit(任务) future.get();//打印线程执行的结果
callable和runable的区别
callable有返回值,runable没有返回值
shutdown和shutdownnow()的区别
1 shutdown()方法在终止前允许执行以前提交的任务
2 shutdownnow()方法阻止等待任务启动并试图停止当前正常执行的任务
如何合理配置线程池大小(检查任务的性质,执行时间,以及依赖性)
1 确定任务的性质 (CPU密集型 ? IO密集型 ? 混合型任务 ? )
2 确定任务的执行时间 (长 ? 短 ? 中 ?)
3 确定任务的依赖性,是否依赖其它的系统资源 (数据连接 ?)
线程池配置方案参考
1 CPU密集型任务 应配置尽可能少的线程数(上下文切换消耗) CPU个数+1
2 IO密集型任务 应配置尽可能多的线程数(IO操作不占用CPU) 两倍CPU个数+1
3 如依赖其它资源,等待时间越长,则CPU空闲时间越长,线程数应设置得越大
4 线程等待时间所占比例越高,需要越多线程,线程CPU时间所占比例越高,需要越少线程