2013-04-17 110 views
3

我有一個類安排如下:Java ExecutorService:我應該在執行之前放置一個鎖嗎?

public class MyClass { 

    ExecutorService pool; 

    public MyClass(){ 
    pool = ... //inited by a class that implements ExecutorService 
    } 

    public final void submit(Runnable run){ 
     pool.execute(run); 
    } 
} 

是方法submit線程安全的,或者我應該使用Lock爲基礎的系統?例如。

ReentrantLock look = new ReentrantLock(); 

    public final void submit(Runnable run){ 
     lock.lock(); 
     try{ pool.execute(run); } finally{lock.unlock();} 
    } 

回答

8

調用ExecutorService#submit時,沒有你不需要鎖。

內存一致性效果:在提交一個Runnable或可調用任務的一個ExecutorService的前一個線程動作發生-之前由該任務,這反過來又發生-之前結果經由未來檢索所採取的任何行動。得到()。

或主叫Executor#execute時:

內存一致性效果:提交Runnable對象到一個執行器之前操作在一個線程發生-之前其執行開始,也許在另一個線程。

+0

謝謝!答案是完整的和詳盡的! –

1

這取決於你如何爲ExecutorService訪問或如何建立您的MyClass。如果在單個線程中創建MyClass的實例,並且在一個線程中也創建了#pool ivar,那麼此類是線程安全的,並且您使用#pool是線程安全的。但是,如果MyClass可以存在於多個線程中(例如首先通過單例,共享工廠或共享列表訪問 - 即不是new MyClass()),那麼它不是線程安全的。這是因爲多個線程可以訪問您的Myclass實例及其單個#pool伊娃。調用提交可以一次完成,但可以同時執行多個線程,因此您的Myclass實例或pool的狀態可能會受到影響。在這種情況下,您的MyClass#submit應該被鎖定同步或管理。由於這是一個小巧的方法,我建議只是同步#submit

同樣,如果在此線程創建您的MyClass實例,但#pool沒有新的創造,在這個線程(pool = new AnExecutorPoolType(...);那麼這個類就再不會是線程安全的。池可以再次從另一個源(如上)訪問的在多線程中是可用的,如果是這種情況,則存在多線程訪問時處於不一致狀態的風險,在這種情況下,應該同步(或通過守護ivar訪問的同步模塊)或管理通過鎖

+0

其實,MyClass是一個枚舉設計用於使用池作爲一個單身人士。 –

+0

我在這裏重新閱讀我的答案時有些驚慌,認爲「看起來不正確」。但是,我將要離開它,因爲我認爲我所做的是...... ExecutorService可能是線程安全的(雖然這實際上取決於實現[儘管java impls是「happen-before」]),但是您的實現的提交可能不是線程安全的。在到達'ExecutorService'之前,你的'Myclass#submit'中可能會出現另一個線程,並導致命令不符合你的預期。所以,你的班級可能需要警惕這一點。 – wmorrison365

+0

另請參見[ThreadPoolExecutor線程安全嗎?](http://stackoverflow.com/questions/1702386/is-threadpoolexecutor-thread-safe)。 – wmorrison365

相關問題