ArrayBlockingQueue+同步 java
ArrayBlockingQueue+synchronized in java
我在我的代码中使用 ArrayBlockingQueue,它有任何元素。但是线程调用了 take 方法。为什么?
我认为应该调用 take 方法之前的 put 方法。文笔不好请见谅。
你怎么知道在项目可用之前它不会阻塞?
您还应该记录从队列中删除的项目。理想情况下,包括一些有助于识别唯一值的 Id,例如放置时的线程名称。
请记住,队列中的方法是原子的,您的日志记录不是,因此与您尝试调试的事件相比,它可能会乱序发生。
为了使这一点更明显,我会在显示哪些线程正在等待的阻塞方法之前添加日志记录。
我还保存了一些东西,以便很容易看出所截取的消息来自何处。这样您就可以看到这些方法正在阻塞并按预期工作。
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class ArrayBlockingQueueExample {
public static void main(String[] args) {
ArrayBlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
Thread[] threads = {
new Producer(blockingQueue),
new Producer(blockingQueue),
new Producer(blockingQueue),
new Producer(blockingQueue),
new Producer(blockingQueue),
new Consumer(blockingQueue),
new Consumer(blockingQueue),
new Consumer(blockingQueue),
new Consumer(blockingQueue),
new Consumer(blockingQueue),
};
for(Thread t: threads) {
t.start();
}
}
static class Consumer extends Thread {
private final BlockingQueue<String> queue;
Consumer(BlockingQueue<String> queue) {
this.queue = queue;
}
@Override
public void run() {
try {
System.out.println("Consumer:" + this.getName() + " waiting... ");
String takenValue = queue.take();
// Logging here may occur out of order in comparison with the producer thread logging.
System.out.println("Consumer:" + this.getName() + " received: " + takenValue);
} catch (InterruptedException e) {
// Reset the interrupted flag on the thread.
Thread.currentThread().interrupt();
e.printStackTrace();
}
}
}
static class Producer extends Thread {
private final BlockingQueue<String> queue;
Producer(BlockingQueue<String> queue) {
this.queue = queue;
}
@Override
public void run() {
try {
String putValue = "Producer:" + this.getName() + " says hello!";
System.out.println("Producer:" + this.getName() + " waiting... ");
queue.put(putValue);
// Logging here may occur out of order in comparison with the consumer thread logging.
System.out.println("Producer:" + this.getName() + " sent: " + putValue);
} catch (InterruptedException e) {
// Reset the interrupted flag on the thread.
Thread.currentThread().interrupt();
e.printStackTrace();
}
}
}
}
使用此代码,您将看到类似于以下输出的内容:
Consumer:Thread-5 waiting...
Consumer:Thread-7 waiting...
Producer:Thread-1 waiting...
Producer:Thread-0 waiting...
Producer:Thread-4 waiting...
Consumer:Thread-9 waiting...
Consumer:Thread-8 waiting...
Consumer:Thread-6 waiting...
Producer:Thread-2 waiting...
Producer:Thread-3 waiting...
Consumer:Thread-6 received: Producer:Thread-0 says hello!
Producer:Thread-2 sent: Producer:Thread-2 says hello!
Consumer:Thread-5 received: Producer:Thread-3 says hello!
Producer:Thread-1 sent: Producer:Thread-1 says hello!
Consumer:Thread-7 received: Producer:Thread-4 says hello!
Consumer:Thread-8 received: Producer:Thread-1 says hello!
Producer:Thread-3 sent: Producer:Thread-3 says hello!
Producer:Thread-4 sent: Producer:Thread-4 says hello!
Consumer:Thread-9 received: Producer:Thread-2 says hello!
Producer:Thread-0 sent: Producer:Thread-0 says hello!
请注意,消费者 (Thread-6) 在第一行记录中收到了来自 Thread-0 生产者的 hello,但是来自 Thread-0 的 sent
记录是记录的最后一行?此顺序与阻塞队列上的放置事件顺序无关。
put()
和take()
的执行顺序无关紧要-效果是一样的,因为它们是阻塞调用。
take()
接受并 returns 下一项,如果 none 可用,请等待。
put()
添加一个项目,如果没有 space 可用,等待被拿走。
我在我的代码中使用 ArrayBlockingQueue,它有任何元素。但是线程调用了 take 方法。为什么? 我认为应该调用 take 方法之前的 put 方法。文笔不好请见谅。
你怎么知道在项目可用之前它不会阻塞?
您还应该记录从队列中删除的项目。理想情况下,包括一些有助于识别唯一值的 Id,例如放置时的线程名称。
请记住,队列中的方法是原子的,您的日志记录不是,因此与您尝试调试的事件相比,它可能会乱序发生。
为了使这一点更明显,我会在显示哪些线程正在等待的阻塞方法之前添加日志记录。
我还保存了一些东西,以便很容易看出所截取的消息来自何处。这样您就可以看到这些方法正在阻塞并按预期工作。
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class ArrayBlockingQueueExample {
public static void main(String[] args) {
ArrayBlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
Thread[] threads = {
new Producer(blockingQueue),
new Producer(blockingQueue),
new Producer(blockingQueue),
new Producer(blockingQueue),
new Producer(blockingQueue),
new Consumer(blockingQueue),
new Consumer(blockingQueue),
new Consumer(blockingQueue),
new Consumer(blockingQueue),
new Consumer(blockingQueue),
};
for(Thread t: threads) {
t.start();
}
}
static class Consumer extends Thread {
private final BlockingQueue<String> queue;
Consumer(BlockingQueue<String> queue) {
this.queue = queue;
}
@Override
public void run() {
try {
System.out.println("Consumer:" + this.getName() + " waiting... ");
String takenValue = queue.take();
// Logging here may occur out of order in comparison with the producer thread logging.
System.out.println("Consumer:" + this.getName() + " received: " + takenValue);
} catch (InterruptedException e) {
// Reset the interrupted flag on the thread.
Thread.currentThread().interrupt();
e.printStackTrace();
}
}
}
static class Producer extends Thread {
private final BlockingQueue<String> queue;
Producer(BlockingQueue<String> queue) {
this.queue = queue;
}
@Override
public void run() {
try {
String putValue = "Producer:" + this.getName() + " says hello!";
System.out.println("Producer:" + this.getName() + " waiting... ");
queue.put(putValue);
// Logging here may occur out of order in comparison with the consumer thread logging.
System.out.println("Producer:" + this.getName() + " sent: " + putValue);
} catch (InterruptedException e) {
// Reset the interrupted flag on the thread.
Thread.currentThread().interrupt();
e.printStackTrace();
}
}
}
}
使用此代码,您将看到类似于以下输出的内容:
Consumer:Thread-5 waiting...
Consumer:Thread-7 waiting...
Producer:Thread-1 waiting...
Producer:Thread-0 waiting...
Producer:Thread-4 waiting...
Consumer:Thread-9 waiting...
Consumer:Thread-8 waiting...
Consumer:Thread-6 waiting...
Producer:Thread-2 waiting...
Producer:Thread-3 waiting...
Consumer:Thread-6 received: Producer:Thread-0 says hello!
Producer:Thread-2 sent: Producer:Thread-2 says hello!
Consumer:Thread-5 received: Producer:Thread-3 says hello!
Producer:Thread-1 sent: Producer:Thread-1 says hello!
Consumer:Thread-7 received: Producer:Thread-4 says hello!
Consumer:Thread-8 received: Producer:Thread-1 says hello!
Producer:Thread-3 sent: Producer:Thread-3 says hello!
Producer:Thread-4 sent: Producer:Thread-4 says hello!
Consumer:Thread-9 received: Producer:Thread-2 says hello!
Producer:Thread-0 sent: Producer:Thread-0 says hello!
请注意,消费者 (Thread-6) 在第一行记录中收到了来自 Thread-0 生产者的 hello,但是来自 Thread-0 的 sent
记录是记录的最后一行?此顺序与阻塞队列上的放置事件顺序无关。
put()
和take()
的执行顺序无关紧要-效果是一样的,因为它们是阻塞调用。
take()
接受并 returns 下一项,如果 none 可用,请等待。
put()
添加一个项目,如果没有 space 可用,等待被拿走。