EffectiveJava第十章第三节

executor和task优先于线程

JDK1.5之后引入了并发线程框架可以更加优雅地实现异步多线程问题,同时还提供了线程池,定时重复任务等强大的功能。

并发线程框架的基本使用如下:

//创建一个单线程线程执行器  
ExecutorService executor = Executors.newSingleThreadExecutor();  
//执行线程任务  
executor.execute(runnable);  
//任务结束线程终止  
executor.shutdown();  

线程框架创建线程池的方法如下:

//创建缓冲线程池  
ExecutorService executor = Executors.newCachedThreadPool();  
//创建固定数目线程池  
ExecutorService executor = Executors.newFixedThreadPool(int threadNum); 

线程框架创建定时任务方法如下:

//创建单线程定时任务  
ScheduleExecutorService executor = Executors.newSingleThreadScheduleExecutor();  
//创建线程池定时任务  
ScheduleExecutorService executor = Executors.newScheduleThreadPool(int threadNum);  
//执行给定延迟时间后的一次操作  
executor.schedule(Runnable runnable, long delay, TimeUnit unit);  
//执行固定频率任务,给定首次延迟,然后间隔给定时间重复执行  
executor.scheduleAtFixedRate(Runnable runnable, long initialDelay, long period, TimeUnit unit);  
//执行固定延迟任务,给定首次延迟,然后每隔给定延迟时间重复执行  
executor.scheduleWithFixedDelay(Runnable runnable, long initialDelay, long delay, TimeUnit unit);  

Timer和线程池定时任务的对比:

  • Timer实现定时任务更加简单,Timer只用一个线程来执行任务,在面对长期运行的任务时,会影响到定时的准确性。如果Timer唯一的线程抛出未被捕获的异常,Timer就会停止执行。
  • 线程池定时任务支持多个线程更加灵活,可以优雅地从抛出的未受检异常的任务中恢复。

你不仅应该尽量不要编写自己的工作队列,而且还应该尽量不直接使用线程。现在关键的抽象不再是Thread了,它以前可是既充当工作单元,又是执行机制。现在工作单元和执行机制是分开的。现在关键的抽象是工作单元,称作任务(task)。任务有两种:Runnable及其近亲Callable(它与Runnable类似,但它会返回值)。执行任务的通用机制是executor service。如果你从任务的角度来看问题,并让一个exeutor service替你执行任务,在选择适当的执行策略方面就获得了极大的灵活性。从本质上讲,Executor Framework所做的工作是执行,犹如Collections Framework所做的工作是聚集一样。

可参考工程SingleThreadPool类进一步学习。

你可能感兴趣的:(EffectiveJava第十章第三节)