我正在尝试Java线程生产者和消费者计划。 但消费者线程总是进入等待状态。
我无法调试消费者线程总是进入等待状态或生产者不通知消费者线程的问题
请帮我解决这个问题。这些计划如下。
communicator类调用生产者和消费者类
public class Communicator {
Thread t = null;
Thread t1 = null;
public void runThread() {
Producer p = new Producer();
Consumer c = new Consumer(p);
t = new Thread(p);
t1 = new Thread(c);
t.start();
t1.start();
Thread tr = new Thread() {
public void run() {
for (int i = 0; i < 30; i++) {
System.out.println("t::::::::::::: " + t.getState());
System.out.println("t1::::::::::::: " + t1.getState());
try {
Thread.sleep(2000);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
};
tr.start();
}
public static void main(String[] args) {
Communicator c = new Communicator();
c.runThread();
}
}
这是生产者类,它将数据附加到stringbuffer中并通知消费者类
public class Producer extends Thread {
public StringBuffer sb;
public Producer() {
sb = new StringBuffer();
}
public void run() {
synchronized (sb) {
try {
System.out.println("Bala");
sb.append("murugan");
sb.notify();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
以下是消费者类代码。它等待从生产者类获得通知。
public class Consumer extends Thread {
public Producer p;
public Consumer(Producer p) {
this.p = p;
}
public void run(){
synchronized (p.sb) {
try {
p.sb.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(p.sb);
}
}
}
答案 0 :(得分:0)
Producer
已经终止,并且在notify()
调用Consumer
之前已经调用了wait()
。
自Producer
和Consumer
extends
Thread
以来,请将Communicator
类更新为:
public class Communicator {
public void runThread() {
final Producer p = new Producer();
final Consumer c = new Consumer(p);
p.start();
c.start();
Thread tr = new Thread() {
public void run() {
for (int i = 0; i < 30; i++) {
System.out.println("t::::::::::::: " + p.getState());
System.out.println("t1::::::::::::: " + c.getState());
try {
Thread.sleep(2000);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
};
tr.start();
}
public static void main(String[] args) {
Communicator c = new Communicator();
c.runThread();
}
}
如果Producer
尚未终止[if (p.getState() != Thread.State.TERMINATED)
],那就是Consumer
等待的唯一时间:
public class Consumer extends Thread {
public Producer p;
public Consumer(Producer p) {
this.p = p;
}
public void run() {
synchronized (p.sb) {
try {
if (p.getState() != Thread.State.TERMINATED) {
p.sb.wait();
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(p.sb);
}
}
}
答案 1 :(得分:0)
当前代码中几乎没有问题,其中Consumer线程始终处于等待状态,而生产者已经终止。
此外,您的StringBuffer
对象需要为volatile
,以便生产者线程写入将被刷新&amp;可用于其他主题。
除此之外,我还修改了您的Producer
和Consumer
代码,使其更加真实(在while
循环中运行,生成一些数据,另一个生成一些数据)如下图所示:(我还加入了1秒的睡眠时间以较慢的速度运行,以便您能更好地理解事物):
消费者类:
public class Producer extends Thread {
public volatile StringBuffer sb;
public Producer() {
sb = new StringBuffer();
sb.append("");
}
public void run() {
synchronized (sb) {
try {
while(true) {
Thread.sleep(1000);
if(sb.toString().equals("")) {
sb.append("murugan");
System.out.println(" producing sb completed *** ");
sb.notify();
} else {
sb.wait();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
消费者类:
public class Consumer extends Thread {
public Producer p;
public Consumer(Producer p) {
this.p = p;
}
public void run(){
synchronized (p.sb) {
try {
while(true) {
Thread.sleep(1000);
if(p.sb.toString().equals("")) {
p.sb.wait();
} else {
String str = p.sb.toString();
System.out.println(" consuming sb completed **** "+str);
p.sb.replace(0, str.length(), "");
p.sb.notify();
}
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(p.sb);
}
}
}
答案 2 :(得分:0)
对于您的问题,&#34;我无法调试消费者线程始终进入等待状态或生产者未通知消费者线程&#34;的问题。 实际上,您的消费者并不总是处于等待状态。 您可以在p.sb.wait()之前放置Thread.sleep(1000);在你的Consumer类中,你可以看到&#34; consumerThread ::::::::::::: RUNNABLE&#34;一次。 恕我直言,您的消费者代码运行得太快而无法获得等待状态,因此您错过了可运行状态。您可以从其他答案中了解更多信息。
答案 3 :(得分:0)
根据您的代码,Consumer Thread
会等待Producer
到notify
关于StringBuffer
中附加的字符串。
Producer
主题有机会获得shared StringBuffer object
上的锁定(它进入synchronized block
),则Consumer Thread
将进入Blocked state
{1}}(将无法输入synchronized block
),因为它也是Lock的竞争者(两者都争夺获取同一共享对象的锁定)。 synchronized block
并获得终止。 请注意,通知代码不会产生任何影响,因为消费者线程尚未等待共享对象,因为尚未进入同步块 Consumer thread
有机会获得lock
并输入synchronized block
它waits
以获取有关共享对象的通知。但是,由于制作人已经终止,没有人将通知发送给Consumer thread
,并且它仍处于Waiting
州。 修复:在您的情况下,您可以简单地确保首先启动Consumer thread
并在生产者线程之前获取锁定。为此,您可以在启动Consumer线程后让主线程休眠一段时间。
t = new Thread(p);
t1 = new Thread(c);
t1.start();
try {
Thread.sleep(1000);
}catch (InterruptedException e) {
e.printStackTrace();
}
t.start();
关键点:如果您只有2个主题,则一个主题应调用notify
和wait
。其他线程一旦被通知,只有竞争Lock的线程将获得锁定并完成其工作。完成其工作后,它应该调用notify并等待另一个线程完成工作并在完成后发出通知。这样,两个线程都将有机会一个接一个地完成工作。