线程调用wait()后如何确保事件发生?

时间:2015-08-21 21:49:43

标签: java multithreading synchronization producer-consumer

我有一个高尔夫球手线程的当前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是一个对象,代表高尔夫球手共享的golfBall个对象的集合,以及随机时间“拿起”高尔夫球的线程。

我想做什么:

显然,如果sharedStash的大小小于5,高尔夫球手就不能拿起一桶球而必须等到收集器线程熄灭并将球添加回{{1} }。

比如说当前sharedStash大小是3,而sharedStash线程'Bob'正试图填满他的球。他必须等到收集器线程从场中收集球并将它们添加到Golfer。但是目前正在发生的事情是,当高尔夫球手线'鲍勃'试图填满他的水桶时,它只是打印:“高尔夫球手鲍勃试图填满他的水桶”然后其他线上有球的球开始击球,直到收集者线程来到高尔夫球场,收集球,将它们添加到sharedStash。如果收集器添加的数量超过5,应该发生什么高尔夫球手鲍勃应该在任何其他高尔夫球手线程之前获得他们的存储桶

然而,现在发生的事情是,其他一些sharedStash将在“Bob”之前填满,即使bob等待的时间最长。

我该如何解决这个问题?

一个例子:

Golfer

1 个答案:

答案 0 :(得分:1)

您的代码不会努力建立排队系统。你希望高尔夫球手排队等候吧?因此,当需要上线时,实际上让高尔夫球手加入一条线,也称为BlockingQueue

BlockingQueue作为构造函数的一部分传递给每个Runnable。在这种情况下,您甚至不需要使用synchronized关键字,因为您将阻止poll方法。换句话说,在高尔夫球手线上:

private BlockingQueue<Bucket> queue;

public void getMoreBalls() {
    queue.poll(ballQueue);
}

在Bollie线上:

private BlockingQueue<Bucket> queue;

public void addBucketToQueue() {
   queue.offer(new Bucket());
   stash -= 5;
}

显然,这不是完整的代码,但我认为你可以自己充实。