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类进一步学习。
网友评论