[英]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.