2009-08-17 75 views
4

是否有確定的方法來確保線程在Java中相互隔離?我有一個半星期的問題,由於靜態變量和其他非我無法控制的事情,執行各種第三方源代碼的線程仍然發生衝突。Java中的線程隔離

我知道一個系統可以像我想要的那樣運行儘可能多的項目實例。但是當試圖將所有東西都合併到一個線程化的單個可執行文件時,總會有錯誤和異常。

我幾乎在爲我想要的這個程序的每個實例啓動一個新的進程,但我真的寧願不走這條路線(它會消除大量的實時數據I收集,以及妨礙我殺死目標進程的能力。)

建議?謝謝!

回答

9

如果您要使用的庫的作者沒有將其代碼設計爲線程安全,那麼除了防止兩個線程同時調用它之外,幾乎沒有什麼可以輕鬆完成的。

你可以用類加載器拉一些技巧,但這往往會導致一個全新的複雜世界。爲了闡述,如果使用不同的類加載器,可以將相同的類加載兩次(或更多次)到相同的JVM中,因此可以有效地獲得靜態變量的獨立副本。一些Java EE應用程序服務器利用了這種分開的類加載器。這反過來又導致了當庫本身開始執行一些反射和動態類加載時使用哪個類加載器和類路徑的問題。除非你的需求非常好,否則我不會推薦這個appraoch。

通過偏好將是:

1)。爲不安全的代碼提供單線程工作程序。儘量在多線程應用程序中儘可能多地完成工作,儘可能少地投入工作人員。 2)。如果工作人員是您處理的主要部分,那麼您確實需要並行執行,將工作人員分成多個獨立的進程,使用一些IPC通信來分享工作。這感覺就像一個JMS排隊解決方案可能很好地工作。 3)。如果您無法承擔IPC overhea,請嘗試找到libaries的線程安全替代方案,或者如果您對作者有影響,請讓他們修復代碼。真的不應該很難增加它們的並行性。

0

不幸的是,沒有辦法做到這一點。如果線程訪問共享資源,他們應該根據需要鎖定這些資源,否則你的程序肯定會面臨共享狀態的損壞。

也許您可以以允許您同步訪問的方式打包共享資源?

0

我幾乎在剛剛 推出一個新的進程對這一計劃的每個 情況下,我想, 點,但我真的寧願不走這條路線 (它會消除很多 實時數據我收集,以及 的阻礙我殺死一個目標 處理能力。)

通過它的聲音,你想重用代碼真的不是設計用來在多線程應用程序中。在這種情況下,爲每個實例啓動一個單獨的進程可能實際上是您的最佳選擇。實際上,這不應該妨礙你殺死每個實例的能力,而應該讓它更容易做到;見Process.destroy()

雖然不清楚「實時」是什麼意思,但是如果每個子進程都寫入其標準輸出,那麼可以編寫控制程序來讀取並整理輸出。

4

實現各種第三方源代碼的線程由於靜態變量和其他非我無法控制的事情而保持衝突。

如果確實如此,那麼我認爲你必須走下單獨流程的道路。如果您調用的代碼不是線程安全的,那麼您所能做的就是確保此代碼一次僅由一個進程調用。這基本上消除了在不同線程中運行它的優點。

以及妨礙我殺了有針對性的處理

我不明白你的意思在這裏的能力。只有在流程中您可以安全地終止處理,如果您無法完全控制所有運行的代碼,則無法通過線程安全地執行此操作。

參見this question關於類似問題的討論。

0

您可以爲每個線程使用單獨的類加載器來加載要保持分離的第三方庫。

0

您可以嘗試將資源放在單個執行程序中,以這種方式永遠不會有兩個並行運行的進程。

你能做到這一點的方法是執行者的手段:

class Foo { 
    private ExecutorService executor = Executors.newSingleThreadExecutor(); 

    public void addTask(Runnable bar) { 
    executor.submit(bar); 
    } 
}