问题描述
我正在尝试使用以下代码的线程执行一些生产者消费者 poc,一轮后,两个线程都处于等待状态。 但我希望它们继续循环,其中一个线程不断增加计数器而其他线程不断减少。
有人可以建议我缺少什么吗?
public class ProducerConsumerWithThreads {
synchronized void withdrawBoxConsumer() {
if(Box > 0){
Box --;
System.out.println("Took one Box Now Boxes left "+ Box);
}
if(Box == 0) {
System.out.println("Please put more Boxes");
notify();
try{wait();}catch(Exception e){
System.out.println("Exception occured" + e.fillInStackTrace());
}
} else {
withdrawBoxConsumer();
}
}
synchronized void putBoxProducer() {
if(Box < 10){
Box ++;
System.out.println("Put one Box Now Boxes are "+ Box);
}
if(Box == 10) {
System.out.println("Please Consume Boxes");
notify();
try{wait();}catch(Exception e){
System.out.println("Exception occured" + e.fillInStackTrace());
}
} else {
putBoxProducer();
}
}
public int Box = 5;
public static void main(String[] args) throws InterruptedException {
//pipeline of 10 Boxes
//consumer takes one at a time .. till its empty
int BoxLimit = 10;
final int Box = 5;
final ProducerConsumerWithThreads c=new ProducerConsumerWithThreads();
new Thread(){
public void run(){c.withdrawBoxConsumer();}
}.start();
new Thread(){
public void run(){c.putBoxProducer();}
}.start();
}
}
我得到的输出是:
Took one Box Now Boxes left 4
Took one Box Now Boxes left 3
Took one Box Now Boxes left 2
Took one Box Now Boxes left 1
Took one Box Now Boxes left 0
Please put more Boxes
Put one Box Now Boxes are 1
Put one Box Now Boxes are 2
Put one Box Now Boxes are 3
Put one Box Now Boxes are 4
Put one Box Now Boxes are 5
Put one Box Now Boxes are 6
Put one Box Now Boxes are 7
Put one Box Now Boxes are 8
Put one Box Now Boxes are 9
Put one Box Now Boxes are 10
Please Consume Boxes
我期待它按照逻辑继续循环下去!有人可以帮忙吗?
解决方法
您的问题是一个非常基本的流程问题:当调用“notify”并且等待的线程再次启动时,该方法完成并且线程停止运行。
请注意,您的两个方法在同一个对象上同步,因此它们永远不会同时运行。例如。一个线程将获得监视器,并递增/递减该框,直到它最终等待。然后另一个线程会去,直到它等待。
在使用等待和通知时,您还有其他一些非常常见的问题。
synchronized void withdrawBoxConsumer() {
while( !Thread.currentThread().isInterrupted() ) {
if(box > 0){
box --;
System.out.println("Took one box now boxes left "+ box);
}
while(box == 0) {
System.out.println("Please put more boxes");
notifyAll();
try{
wait();
}catch(Exception e){
throw new RuntimeException(e);
}
}
}
}
synchronized void putBoxProducer() {
while( !Thread.currentThread().isInterrupted() ) {
if(box < 10){
box ++;
System.out.println("Put one box now boxes are "+ box);
}
while(box == 10) {
System.out.println("Please Consume boxes");
notifyAll();
try{
wait();
}catch(Exception e){
throw new RuntimeException(e);
}
}
}
}
- 我将其设为非递归,因为按照您的做法,堆栈会溢出。
- 由于虚假唤醒,等待条件处于循环中。
- 我切换到
notifyAll
通知只会唤醒一个等待线程,在这种情况下应该没问题,但最好是安全的。 -
box
理想情况下应该是一个并发类或 volatile,但由于您总是在同步方法中工作,所以应该没问题。 - 同样,
box++
和box--
是竞争条件。 -
e.fillInStackTrace()
不是您想要使用的。
public class ProducerConsumerWithThreads {
synchronized void withdrawBoxConsumer() {
if(box > 0){
box --;
System.out.println("Took one box now boxes left "+ box);
}
if(box == 0) {
System.out.println("Please put more boxes");
notify();
try{wait();}catch(Exception e){
System.out.println("Exception occured" + e.fillInStackTrace());
}
}
withdrawBoxConsumer();
}
synchronized void putBoxProducer() {
if(box < 10){
box ++;
System.out.println("Put one box now boxes are "+ box);
}
if(box == 10) {
System.out.println("Please Consume boxes");
notify();
try{wait();}catch(Exception e){
System.out.println("Exception occured" + e.fillInStackTrace());
}
}
putBoxProducer();
}
public int box = 5;
public static void main(String[] args) throws InterruptedException {
//pipeline of 10 boxes
//consumer takes one at a time .. till its empty
int boxLimit = 10;
final int box = 5;
final ProducerConsumerWithThreads c=new ProducerConsumerWithThreads();
new Thread(){
public void run(){c.withdrawBoxConsumer();}
}.start();
new Thread(){
public void run(){c.putBoxProducer();}
}.start();
}
}