[英]Ensuring all waiting threads complete
我正在建立一個系統,其中調用線程的進度取決於兩個變量的狀態。 一個變量由外部源(與客戶端線程分離)偶爾更新,並且在兩個變量的條件下多個客戶端線程被阻塞。 系統是這樣的
TypeB waitForB() { // Can be called by many threads.
synchronized (B) {
while (A <= B) { B.wait(); }
A = B;
return B;
{
}
void updateB(TypeB newB) { // Called by one thread.
synchronized (B) {
B.update(newB);
B.notifyAll(); // All blocked threads must receive new B.
}
}
一旦更新了B,我需要所有阻塞的線程來接收B的新值。 但是問題是,一旦單個線程完成並更新了A,等待條件就再次變為真,因此其他一些線程被阻塞並且不接收B的新值。是否有辦法確保只有最后一個線程在B更新A或其他獲得此行為的方式上被阻止了?
我的建議是使用基於事件的方法,其中線程要了解新的B
值,只需注冊更改! 而單線程只是調用(觸發)它們。
這樣的事情。
首先聲明事件標志。
interface EventListener{
void onUpdate(TypeB oldOne,TypeB newOne);
}
然后將其實現為偵聽器。
class ManyThread implements EventListener,Runnable{
...
private TypeA a;
synchronized void onUpdate(TypeB oldOne,TypeB newOne){
if(!oldOne.equals(newOne)){a=newOne;this.notify();}
}
public ManyThread(){SingleThread.registerListener(this);}
public synchronized void run(){
this.wait();//waiting for an event!
//some business
}
...
}
然后提供事件發布者。
final class EventMgr{//would be as a singleton guy too
private EventMgr(){}
static private java.util.List<EventListener> li=new java.util.ArrayList<EventListener>();
static synchronized public void registerListener(EventListener e){li.add(e);}
static synchronized void triggerListeners(TypeB oldOne,TypeB newOne){
for(EventListener e:li){e.onUpdate(oldOne,newOne)}
}
}
和簡單的觸發偵聽器由EventMgr
家伙
class SingleThread{
TypeB oldOne,B;
void updateB(TypeB newB) { // Called by one thread.
synchronized (B) {
oldOne=B.clone();
B.update(newB);
//B.notifyAll();
EventMgr.triggerListeners(oldOne,B);
}
}
}
我有以下想法:為了讓線程計數器等待B的“良好”值,首先喚醒它們將緩存該良好值,並讓其他讀者在此之前讀取它。 我們將新讀者拒之門外,直到所有之前的回合線程完成。
這是代碼概述:
final AtomicInteger A = new AtomicInteger(-1), B = new AtomicInteger(-1);
int cachedB = -1;
int readersCount;
int waitForB() throws InterruptedException { // Can be called by many threads.
synchronized (B) {
while (cachedB != -1) B.wait();
readersCount ++;
while (A.get() <= B.get()) { B.wait(); }
if (cachedB == -1) {
cachedB = B.get();
A.set(B.get());
readersCount--;
if (readersCount == 0) { cachedB = -1; B.notifyAll(); }
return B.get();
} else {
int ret = cachedB;
readersCount--;
if (readersCount == 0) { cachedB = -1; B.notifyAll(); }
return ret;
}
}
}
void updateB(int newB) { // Called by one thread.
synchronized (B) {
B.set(newB);
B.notifyAll(); // All blocked threads must receive new B.
}
}
我不確定這是否是100%線程安全的,但尚未發現任何問題。 這個想法是這樣的:
CyclicBarrier barrier;
AtomicInteger count = 0;
TypeB waitForB() { // Can be called by many threads.
synchronized (B) {
count++;
while (A <= B) { B.wait(); }
count--;
{
if (barrier != null) { barrier.await(); }
return B;
}
class UpdateA implements Runnable {
void run() {
A = B;
}
}
void updateB(TypeB newB) { // Called by one thread.
synchronized (B) {
B.update(newB);
barrier = new CyclicBarrier(count, new UpdateA);
B.notifyAll(); // All blocked threads must receive new B.
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.