我有 Golfer 线程的当前 run()
方法:
public void run() {
while (done.get() != true) { // this is just a flag to see if the GolfRange is open
synchronized (sharedStash) {
System.out.println(">>> Golfer #" + myID
+ " trying to fill bucket with " + getBallsPerBucket() + " balls.");
while (sharedStash.getSizeStash().intValue() < 5) {
try {
System.out.println(myID + "is still waiting, size = "
+ sharedStash.getSizeStash().intValue());
sharedStash.wait(1000);
} catch (InterruptedException ex) {
Logger.getLogger(Golfer.class.getName())
.log(Level.SEVERE, null, ex);
}
}
golferBucket = sharedStash.getBucketBalls();
System.out.println("<<< Golfer #" + myID + " filled bucket with "
+ getBallsPerBucket() + " balls, size = "
+ sharedStash.getSizeStash());
}
}
}
sharedStash
是一个对象,表示由 Golfer 和随机时间“拾起”高尔夫球的线程共享的 golfBall
对象的集合。
我想做的事情:
显然,如果sharedStash
的大小小于5,高尔夫球手就无法拿起一桶球,必须等到收集器线程退出并将球添加回sharedStash
。
例如,当前 sharedStash
大小为 3,并且 Golfer
线程“Bob”正在尝试填满他的球桶。他必须等到 Collector 线程从场上收集球并将它们添加到 sharedStash
中。但目前发生的情况是,当高尔夫球手线程“鲍勃”试图填满他的水桶时,它只会打印:“高尔夫球手鲍勃正在尝试填满他的水桶”,然后其他桶中有球的线程开始撞击,直到收集器线程来到高尔夫球场,收集球,将它们添加到 sharedStash
中。如果收集器添加的数量超过 5,应该发生高尔夫球手鲍勃应该在任何其他高尔夫球手线程之前拿到他的水桶。
但是,现在发生的情况是,即使鲍勃等待的时间最长,其他高尔夫球手
也会在“鲍勃”之前填满。
我该如何解决这个问题?
示例:
>>> Golfer #1 trying to fill bucket with 5 balls.
<<< Golfer #1 filled bucket with 5 balls, size = 15
>>> Golfer #5 trying to fill bucket with 5 balls.
<<< Golfer #5 filled bucket with 5 balls, size = 10
>>> Golfer #2 trying to fill bucket with 5 balls.
<<< Golfer #2 filled bucket with 5 balls, size = 5
>>> Golfer #3 trying to fill bucket with 5 balls.
<<< Golfer #3 filled bucket with 5 balls, size = 0
>>> Golfer #4 trying to fill bucket with 5 balls.
Golfer #1 hit ball #1 onto field.
Golfer #3 hit ball #16 onto field.
Golfer #5 hit ball #6 onto field.
Golfer #1 hit ball #2 onto field.
Golfer #2 hit ball #11 onto field.
*********** Bollie collecting balls ************
*********** Bollie adding 5 balls to stash ************
*********** Bollie added 5 balls to stash ************
Current stash size: 5
Golfer #1 hit ball #3 onto field.
Golfer #2 hit ball #12 onto field.
Golfer #3 hit ball #17 onto field.
Golfer #5 hit ball #7 onto field.
Golfer #1 hit ball #4 onto field.
Golfer #2 hit ball #13 onto field.
Golfer #1 hit ball #5 onto field.
>>> Golfer #1 trying to fill bucket with 5 balls.
<<< Golfer #1 filled bucket with 5 balls, size = 0
Golfer #2 hit ball #14 onto field.
Golfer #5 hit ball #8 onto field.
*********** Bollie collecting balls ************
*********** Bollie adding 9 balls to stash ************
*********** Bollie added 9 balls to stash ************
Current stash size: 9
Golfer #5 hit ball #9 onto field.
Golfer #3 hit ball #18 onto field.
Golfer #1 hit ball #1 onto field.
Golfer #1 hit ball #16 onto field.
Golfer #2 hit ball #15 onto field.
>>> Golfer #2 trying to fill bucket with 5 balls.
<<< Golfer #2 filled bucket with 5 balls, size = 4
Golfer #1 hit ball #6 onto field.
BUILD STOPPED (total time: 7 seconds)
最佳答案
您的代码没有努力建立排队系统。你希望高尔夫球手排队等候,对吗?因此,当需要上线时,实际上让高尔夫球手加入队伍,也称为 BlockingQueue
.
将 BlockingQueue
作为构造函数的一部分传递到每个 Runnable
中。在这种情况下,您甚至不需要使用 synchronized
关键字,因为您将阻止 poll
方法。换句话说,在 Golfer 线程上:
private BlockingQueue<Bucket> queue;
public void getMoreBalls() {
queue.poll(ballQueue);
}
在 Bollie 线程上:
private BlockingQueue<Bucket> queue;
public void addBucketToQueue() {
queue.offer(new Bucket());
stash -= 5;
}
显然,这不是完整的代码,但我认为您可以自己充实它。
关于java - 如何确保线程调用 wait() 之后发生事件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32149762/