技术开发 频道

Spring对JDK 5.0执行器的支持



    但以上这些粗陋的实现并没有多大的实际意义,这也不符合Executor的设计初衷。真正有意义的实现需要引入线程、列队、调度等机制,这样的执行器才更贴近现实的需求。

    Executor接口还有两个子接口:ExecutorService和ScheduledExecutorService。ExecutorService添加了结束任务的管理方法,此外在提交任务时还可以获取一个Future实例,以便通过这个实例跟踪异步任务的运行情况。而ScheduledExecutorService可以对任务进行调度,如指定执行的延迟时间,运行的周期。如ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit)方法将安排一个任务在指定一段延迟时间后运行。

    JDK 5.0本身提供的ThreadPoolExecutor类实现了Executor和ExecutorService这两个接口,它使用一个线程池对提交的任务进行调度。对于需要处理数量巨大的短小的并发任务(诸如 Web 服务器、数据库服务器、邮件服务器之类的应用程序需要处理来源远程的大量短小的任务),采用线程池可以带来明显的好处。为每个请求创建一个新线程的开销很大,对于短小的任务线程创建和销毁的时间可能比处理实际任务的时间还要长。除此以外,活动的线程需要消耗资源,过多的线程将导致大量的内存占用。线程池为线程生命周期开销问题和资源不足问题提供了解决方案。通过对多个任务重用同一线程,线程创建的开销被分摊到了多个任务上。其好处是,由于在任务到达时线程已经存在,所以无意中也消除了任务执行时,因创建线程所带来的延迟。此外,可以通过适当地调整线程池中的参数,让任务的数目超过某个阈值时,强制其它任何新任务阻塞等待,直到获得一个线程来处理为止,从而可以防止资源的无限制占用。

    ThreadPoolExecutor的子类ScheduledThreadPoolExecutor实现了ScheduledExecutorService接口,添加了对任务的调度功能,如指定延迟一小段时间后运行任务,让任务周期性运行。该类明显优于JDK 1.3中的Timer,因为它通过内建的线程池让每个任务在独立的执行线程中运行,而非让所有任务在单一的背景线程中运行。在Timer经常出现的时间漂移,任务挤压等问题基本上得到了规避。 
    java.util.concurrent中为创建这些接口实例提供了一个综合性的工厂类Executors,它拥有以下众多方便的静态工厂方法:
    ●static ExecutorService newFixedThreadPool(int nThreads):创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程;
    ●static ExecutorService newCachedThreadPool():线程池是动态的,不够用时创建新的线程,长时间不用的线程将被回收;
    ●static ScheduledExecutorService newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory):创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。
    来看一个具体的例子:
    代码清单 10 ExecutorExample
package com.baobaotao.basic.executor; import java.util.concurrent.Executor; import java.util.concurrent.Executors; public class ExecutorExample { private Executor executor; ①声明一个执行器 public void setExecutor(Executor executor) { this.executor = executor; } public void executeTasks() {②用执行器执行多个任务 for (int i = 0; i < 6; i++) { executor.execute(new SimpleTask("task" + i)); } } public static void main(String[] args) { ExecutorExample ee = new ExecutorExample();
③通过工厂类创建一个带3个线程固定线程池的执行器
ee.setExecutor(Executors.newFixedThreadPool(3)); ee.executeTasks(); } } class SimpleTask implements Runnable {④任务类 private String taskName; public SimpleTask(String taskName) { this.taskName = taskName; } public void run() { System.out.println("do "+taskName+"... in Thread:" + Thread.currentThread().getId()); } }
运行以上代码,输入以下信息:
do task0... in Thread:7
do task1... in Thread:8
do task2... in Thread:9
do task3... in Thread:7
do task5... in Thread:9
do task4... in Thread:8
可见,这6个任务共享了线程池中的3个线程。由于ExecutorService用线程池中3个线程服务于提交的任务,避免了为每一个任务创建独立线程的代价,具有更高的运行性能。
0
相关文章