2016-12-30 88 views
0

我有一個包含數據的對象,我正在用這個對象(動作將在其方法中使用對象的數據)排隊一個Action(可以執行的方法的接口)和排隊的Actions將從另一個線程執行。Java多線程問題

我想鎖定對象後發送到行動隊列(所以從我的主線程)。

因爲我不希望對象的數據在其他線程通過動作隊列處理之前被更改。

我想從另一個線程解鎖對象,一旦行爲隊列被處理。

代碼說明:

// THREAD 1 
final Object object = getObjectFromSomeWhere(); 

// lock the object here 

concurrentActionQueue.add(new Action() { 
     @Override 
     public void execute() { 
      // will be executed from THREAD 2 
      // do something with object 

      //unlock here once the data is processed 

     } 

你會說,我可以發送對象的副本的動作,但我的對象包含非常大的數據複製花費到太多的時間,所以我不能。

有沒有辦法做到這一點,沒有硬編碼lock()和unlock()方法到我的對象?

+0

消費者生產者也許格局?這裏是一個非常簡單的(不是最好的)[教程](https://www.tutorialspoint.com/javaexamples/thread_procon.htm)以 – AntJavaDev

回答

0

如果你想鎖定所有主線程的執行,你可以使用CountDownLatch

// THREAD 1 
final Object object = getObjectFromSomeWhere(); 

final CountDownLatch latch = new CountDownLatch(1); 

concurrentActionQueue.add(new Action() { 
     @Override 
     public void execute() { 
      // will be executed from THREAD 2 
      // do something with object 

      latch.countDown(); 
     } 
} 

latch.await(); 

如果你想從其他線程被更改鎖定對象數據,但可用線程的執行,你需要在你的Object課程中完成。我相信這不是一個對象。例如,您可以將對該對象的訪問權的Thread引用傳遞給它,並在其中檢查Thread.currentThread() == mAllowedThread;以瞭解此線程是否允許修改對象。

另外,你可以使用一些OO方式來處理這個問題,例如讓你的對象擁有包本地設置器並傳遞一個包含setter的包裝器給這個動作。很難說什麼是解決方案,因爲我沒有看到你的實際問題。希望我的一些建議可以幫助你。

+0

開頭我的問題是,當我發送我的數據(對象)到行動隊列,這是一個很好的格式。但是數據會持久地改變,並且當數據不再是一個很好的格式(同時從線程1被修改)時這個動作可能被執行,這是危險的。我的線程2是一個渲染器,它需要網格的有序數據。 – aqww

+0

你是什麼意思下的「鎖定/解鎖」對象?其他線程在嘗試更改對象時應如何處理? –

+0

那麼有多種可能性,其中一個是其他線程可能必須等到解鎖之後纔對數據進行任何修改。或者我可以硬編碼一些可以在隊列鎖定時對數據進行每次修改的隊列,並在不再鎖定時執行。 – aqww

0

線程之間只有通用的引用是你的對象,因此實現鎖定你必須修改你的對象。如果你不想修改你的對象,你可以寫一個助手類,它將使用倒計時閂鎖來執行任務。並在你的所有線程中傳遞這個輔助類的引用。 看看這是你在找什麼 -

final YourObject object = getObjectFromSomeWhere(); 

class HelperObject { 
YourObject object; 
public HelperObject(YourObject object){ 
this.object = object; 
} 
final CountDownLatch latch = new CountDownLatch(1); 
    public void countDown(){ 
    latch.countDown(); 
    } 

    public void await(){ 
    latch.await(); 
    } 
} 

concurrentActionQueue.add(new Action() { 
    @Override 
    public void execute() { 
     // will be executed from THREAD 2 
     HelperObject helperObj;// do something with object 

     helperObj.countDown(); 
    } 
}