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