淺談Eclipse中的Jobs框架
了解Eclipse多線程機(jī)制,需要先了解一下Jobs框架——這是Eclipse運(yùn)行時(shí)的重要組成部分。Jobs框架介紹如下:
Eclipse 在 org.eclipse.core.runtime.osgi 運(yùn)行時(shí)插件里提供了 Jobs API 。 Jobs API 被廣泛的應(yīng)用到 Eclipse 平臺(tái)中,用戶所開(kāi)發(fā)的 eclipse 插件里。 Job 是 Eclipse 運(yùn)行時(shí)重要的組成部分(基于 equinox 的 OSGi 框架則是 Eclipse 運(yùn)行時(shí)的最重要的組成部分)。 Job 可以理解成被平臺(tái)調(diào)用異步運(yùn)行的代碼塊。 Job 可以異步的執(zhí)行,多個(gè) Jobs 可以并發(fā)執(zhí)行。那么讀者會(huì)問(wèn)了?為什么 eclipse 平臺(tái)要提供這樣的 API 出來(lái),為什么不直接使用 java.lang.Thread 呢?
原因有以下幾點(diǎn):
1)性能更好:通過(guò)使用線程池實(shí)現(xiàn)了線程共享,減少了創(chuàng)建和銷(xiāo)毀線程的開(kāi)銷(xiāo),提高了性能。
2)交互響應(yīng)信息:Job 提供了一個(gè)框架,開(kāi)發(fā)人員使用 Job 很容易實(shí)現(xiàn)與用戶的交互,例如允許用戶取消 Job 的執(zhí)行或者顯示 Job 。
3)調(diào)度的靈活性:可以馬上運(yùn)行一個(gè) Job,可以稍后運(yùn)行一個(gè) Job, 還可以反復(fù)的運(yùn)行一個(gè) Job
4)Job 的監(jiān)聽(tīng)機(jī)制:Job 監(jiān)聽(tīng)器監(jiān)聽(tīng) Job 的狀態(tài)信息,比如,知道一個(gè) Job 何時(shí)開(kāi)始運(yùn)行以及何時(shí)結(jié)束運(yùn)行等。
5)優(yōu)先級(jí)及互斥的靈活應(yīng)用:Job 提供了多種方式來(lái)控制 Job 的調(diào)度,開(kāi)發(fā)者可以設(shè)定 Job 的優(yōu)先級(jí)(讀者應(yīng)注意這一點(diǎn),JobManager 不保證優(yōu)先級(jí)高的 Job 一定比優(yōu)先級(jí)低的 Job 先被調(diào)度執(zhí)行),也可以使用調(diào)度規(guī)則保證 Jobs 的同步與互斥。
下面我們首先介紹一下 Jobs 的框架 , 如圖 1 所示。其囊括了 org.eclipse.core.runtime.jobs 包內(nèi)的所有接口和類(lèi)。
圖 1. Jobs框架
IJobManager 是 Job 管理器類(lèi)的接口,其中定義了一些對(duì) Job 以及 JobFamily 操作的一些 API 。有關(guān) Job 管理器的實(shí)現(xiàn),我們將在線程池機(jī)制一節(jié)中作詳細(xì)介紹。
當(dāng)并發(fā)執(zhí)行多個(gè) Jobs 的時(shí)候,可能會(huì)引發(fā)沖突(Conflict)。 Job 的框架則充分考慮到了這種情況,并提供了管理和避免沖突的工具。 ISchedulingRule 接口,是用來(lái)管理共享資源訪問(wèn)沖突的技術(shù)。它使得 IJobManager 能夠識(shí)別出沖突的 Jobs,進(jìn)而能保證這些不能在一起執(zhí)行的 Jobs 不在同一時(shí)間被調(diào)度或者啟動(dòng)。 ISchedulingRule 接口的子類(lèi) MultiRule 表示一組固定的子調(diào)度規(guī)則,如果任何一個(gè) MultiRule 的子調(diào)度規(guī)則和另一個(gè)調(diào)度規(guī)則相沖突,那么該 MultiRule 和另一個(gè)調(diào)度規(guī)則就會(huì)發(fā)生沖突。形式化的說(shuō),一個(gè)組合調(diào)度規(guī)則表示其所有的子調(diào)度規(guī)則關(guān)于 isConflicting 方法等價(jià)的邏輯交集。組合調(diào)度規(guī)則不會(huì)再包含另一個(gè)組合調(diào)度規(guī)則,如果你把一個(gè)組合規(guī)則作為子規(guī)則加入到另一個(gè)組合規(guī)則中,算法就是該組合規(guī)則的所有子規(guī)則被加入到另一個(gè)組合規(guī)則中去了。
ILock ,鎖是用來(lái)對(duì)排他性資源的訪問(wèn)控制的。鎖是可以重入的,也就是說(shuō)同一個(gè)線程在不釋放已有鎖的情況下,可多次獲取該鎖。當(dāng)成功獲取鎖的次數(shù)和成功釋放鎖的次數(shù)相等時(shí),鎖才能被釋放掉。通過(guò)實(shí)現(xiàn)釋放等待策略,鎖避免了循環(huán)等待的死鎖。如果一組線程陷入一個(gè)死鎖,一個(gè)線程將會(huì)失去它所擁有的鎖,進(jìn)而打破死鎖,使得其它的線程能夠繼續(xù)執(zhí)行。一旦線程獲得了運(yùn)行所需要的所有的鎖,它將獲得對(duì)鎖控制的排他性資源的訪問(wèn)。
當(dāng)一個(gè)線程正等待一個(gè) acquire() 方法調(diào)用的時(shí)候,才可能會(huì)失去鎖 ( 參見(jiàn)本文的線程同步機(jī)制部分 ) 。程序應(yīng)用隊(duì)列(先來(lái)先得)管理不同的線程來(lái)獲取鎖。線程獲取的鎖一定要釋放掉,一般在 finally 程序塊內(nèi)釋放鎖。例如:
- lock.acquire();
- try {
- // ... 執(zhí)行程序 ...
- } finally {
- lock.release();
- }
IJobChangeListener 接口,監(jiān)聽(tīng)到 Job 的狀態(tài)信息,進(jìn)而執(zhí)行相應(yīng)的邏輯操作。
ProgressProvider 類(lèi),為正在運(yùn)行的 jobs 向 Job 管理器提供進(jìn)度控制器。任何時(shí)候,它只有一個(gè)實(shí)例存在。該類(lèi)僅由平臺(tái)相關(guān)的插件內(nèi)部使用。
【編輯推薦】