?
Dokumen ini menggunakan Manual laman web PHP Cina Lepaskan
Spring 2.0 為執(zhí)行器(Executor)處理引入了一個(gè)新的抽象層。Executor是Java 5的名詞,用來(lái)表示線程池的概念。 之所以用這個(gè)奇怪的名詞,是因?yàn)閷?shí)際上不能保證底層實(shí)現(xiàn)的確是一個(gè)池。實(shí)際上,很多情況下,executor只是單線程。 Spring的抽象層幫助你把線程池引入到Java 1.3和1.4環(huán)境中,同時(shí)隱藏了 1.3, 1.4, 5, 和 Java EE環(huán)境中線程池實(shí)現(xiàn)的差異。
Spring的TaskExecutor
接口等同于java.util.concurrent.Executor
接口。
實(shí)際上,它存在的主要原因是為了在使用線程池的時(shí)候,將對(duì)Java 5的依賴抽象出來(lái)。
這個(gè)接口只有一個(gè)方法execute(Runnable task)
,它根據(jù)線程池的語(yǔ)義和配置,來(lái)接受一個(gè)執(zhí)行任務(wù)。
最初創(chuàng)建TaskExecutor
是為了在需要時(shí)給其他Spring組件提供一個(gè)線程池的抽象。
例如ApplicationEventMulticaster
組件、JMS的 AbstractMessageListenerContainer
和對(duì)Quartz的整合都使用了TaskExecutor
抽象來(lái)提供線程池。
當(dāng)然,如果你的bean需要線程池行為,你也可以使用這個(gè)抽象層。
在Spring發(fā)行包中預(yù)定義了一些TaskExecutor
實(shí)現(xiàn)。有了它們,你甚至不需要再自行實(shí)現(xiàn)了。
SimpleAsyncTaskExecutor
類
這個(gè)實(shí)現(xiàn)不重用任何線程,或者說它每次調(diào)用都啟動(dòng)一個(gè)新線程。但是,它還是支持對(duì)并發(fā)總數(shù)設(shè)限,當(dāng)超過線程并發(fā)總數(shù)限制時(shí),阻塞新的調(diào)用,直到有位置被釋放。如果你需要真正的池,請(qǐng)繼續(xù)往下看。
這個(gè)實(shí)現(xiàn)不會(huì)異步執(zhí)行。相反,每次調(diào)用都在發(fā)起調(diào)用的線程中執(zhí)行。它的主要用處是在不需要多線程的時(shí)候,比如簡(jiǎn)單的test case。
這個(gè)實(shí)現(xiàn)是對(duì)Java 5 java.util.concurrent.Executor
類的包裝。有另一個(gè)備選, ThreadPoolTaskExecutor
類,它暴露了Executor
的配置參數(shù)作為bean屬性。很少需要使用ConcurrentTaskExecutor
, 但是如果ThreadPoolTaskExecutor
不敷所需,ConcurrentTaskExecutor
是另外一個(gè)備選。
SimpleThreadPoolTaskExecutor
類
這個(gè)實(shí)現(xiàn)實(shí)際上是Quartz的SimpleThreadPool
類的子類,它會(huì)監(jiān)聽Spring的生命周期回調(diào)。當(dāng)你有線程池,需要在Quartz和非Quartz組件中共用時(shí),這是它的典型用處。
這個(gè)實(shí)現(xiàn)只能在Java 5環(huán)境中使用,但是卻是這個(gè)環(huán)境中最常用的。它暴露的bean properties可以用來(lái)配置一個(gè)java.util.concurrent.ThreadPoolExecutor
,把它包裝到一個(gè)TaskExecutor
中。如果你需要更加先進(jìn)的類,比如ScheduledThreadPoolExecutor
,我們建議你使用ConcurrentTaskExecutor
來(lái)替代。
TimerTaskExecutor
類
這個(gè)實(shí)現(xiàn)使用一個(gè)TimerTask
作為其背后的實(shí)現(xiàn)。它和SyncTaskExecutor
的不同在于,方法調(diào)用是在一個(gè)獨(dú)立的線程中進(jìn)行的,雖然在那個(gè)線程中是同步的。
WorkManagerTaskExecutor
類
這個(gè)實(shí)現(xiàn)使用了CommonJ WorkManager作為其底層實(shí)現(xiàn),是在Spring context中配置CommonJ WorkManager應(yīng)用的最重要的類。和SimpleThreadPoolTaskExecutor
類似,這個(gè)類實(shí)現(xiàn)了WorkManager接口,因此可以直接作為WorkManager使用。
Spring的TaskExecutor
實(shí)現(xiàn)作為一個(gè)簡(jiǎn)單的JavaBeans使用。在下面的示例中,我們定義一個(gè)bean,使用 ThreadPoolTaskExecutor
來(lái)異步打印出一系列字符串。
import org.springframework.core.task.TaskExecutor; public class TaskExecutorExample { private class MessagePrinterTask implements Runnable { private String message; public MessagePrinterTask(String message) { this.message = message; } public void run() { System.out.println(message); } } private TaskExecutor taskExecutor; public TaskExecutorExample(TaskExecutor taskExecutor) { this.taskExecutor = taskExecutor; } public void printMessages() { for(int i = 0; i < 25; i++) { taskExecutor.execute(new MessagePrinterTask("Message" + i)); } } }
可以看到,無(wú)需你自己從池中獲取一個(gè)線程來(lái)執(zhí)行,你把自己的Runnable
類加入到隊(duì)列中去,TaskExecutor
使用它自己的內(nèi)置規(guī)則來(lái)決定何時(shí)應(yīng)該執(zhí)行任務(wù)。
為了配置TaskExecutor
使用的規(guī)則,暴露了簡(jiǎn)單的bean properties。
<bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"> <property name="corePoolSize" value="5" /> <property name="maxPoolSize" value="10" /> <property name="queueCapacity" value="25" /> </bean> <bean id="taskExecutorExample" class="TaskExecutorExample"> <constructor-arg ref="taskExecutor" /> </bean>