这是我的代码:
public class ProducerConsumer
{
public static void main(String[] args)
{
ProduceCosumeData p = new ProduceCosumeData();
ProducerT pt= new ProducerT(p); // with p obj i am creating thread
ConsumerT ct=new ConsumerT(p); // with same p obj i am creating thread
pt.start();
ct.start(); //i am starting 2 threads
}
}
class ProduceCosumeData
{
boolean flag;
public synchronized void printStringP(int n)
{
for(int i=0;i<n;i++)
{
try{
if(flag) //for frist time flag is flase so, wait will skip
wait();
else
flag=true; //for next time onwards wait() will get call
System.out.print("Pay");
notify();//after this why my wait() not canceling in inprintStringC()
}catch(Exception e)
{
System.out.print(e);
}
}
}
public synchronized void printStringC(int n)
{
for(int i=0;i<n;i++)
{
try{
wait(); // why it is not out of this after notify()
System.out.print("Tm");
notify();
}catch(Exception e)
{
System.out.print(e);
}
}
}
}
class ProducerT extends Thread
{
ProduceCosumeData p;
ProducerT(ProduceCosumeData p)
{
this.p=p; // i am saving the same obj for both threads
}
public void run()
{
p.printStringP(10); //it will print 10 times pay
}
}
class ConsumerT extends Thread
{
ProduceCosumeData p;
ConsumerT(ProduceCosumeData p)
{
this.p=p; // i am saving the same obj for both threads
}
public void run()
{
p.printStringC(10); //it will print 10 times tm
}
}
我期待以下输出:
PayTm
PayTm
PayTm
...... 10次
但是我得到的输出是:
支付..
接下来是漫长的等待。
以上两个功能在同一个对象中 为什么通知不释放wait()函数?即使我使用notifyAll(),输出也保持不变。
答案 0 :(得分:1)
在你的代码中,你的一个线程正在调用notify而另一个线程仍未等待。这会导致两个线程等待死锁。
您需要修复对同步标志的使用,如果不需要,请不要调用wait。此外,在wait()是一个好习惯之后,仍然可以检查锁定条件。
这是您使用固定标志的ProduceConsumeData
课程:
class ProduceCosumeData
{
boolean flag;
public synchronized void printStringP(int n)
{
for(int i=0;i<n;i++)
{
try{
while (flag == true) {
wait();
}
flag=true;
System.out.print("Pay");
notify();
}catch(Exception e)
{
System.out.print(e);
}
}
}
public synchronized void printStringC(int n)
{
for(int i=0;i<n;i++)
{
try{
while(flag == false) {
wait();
}
System.out.print("Tm");
flag = false;
notify();
}catch(Exception e)
{
System.out.print(e);
}
}
}
}
答案 1 :(得分:-1)
在printStringP
的第二次迭代中,属性flag
为true
,然后两个线程正在等待。
答案 2 :(得分:-1)
您在方法中使用了通用wait()
和同步。尝试使用对象同步版本,例如synchronized(this){ wait(); }
,以防止同一对象上多个线程的循环依赖,这对任何多线程程序都非常危险。
或者更简单地说,在clone()
类中实现一个正确的ProducerConsumerData
方法,然后在第一个线程中传递此对象,然后传递给它的克隆。尝试在第二个线程的构造函数中使用p.clone()
而不是p
。
如上所述,你可以使printStringP()的notify()仅在flag为true时被调用,而不是总是。
答案 3 :(得分:-1)
这是一种典型的误解,几乎每个试图使用wait
和notify
的人都会绊倒。真的,他们已经老了,坏了,他们甚至不应该再被教导了。
printStringP
来电时notify()
printStringC
尚未等待。
class ProduceCosumeData {
// Variable shared between threads should be volatile.
volatile boolean flag;
public synchronized void printStringP(int n) {
for (int i = 0; i < n; i++) {
try {
//for frist time flag is flase so, wait will skip
if (flag) {
System.err.println("Waiting in printStringP");
wait();
} else {
System.err.println("flag now true");
flag = true; //for next time onwards wait() will get call
}
System.out.print("Pay");
System.err.println("printStringP notify");
notify();//after this why my wait() not canceling in inprintStringC()
} catch (Exception e) {
System.out.print(e);
}
}
}
public synchronized void printStringC(int n) {
for (int i = 0; i < n; i++) {
try {
System.err.println("Waiting in printStringC");
wait(); // why it is not out of this after notify()
System.out.print("Tm");
System.err.println("printStringC notify");
notify();
} catch (Exception e) {
System.out.print(e);
}
}
}
}
class ProducerT extends Thread {
ProduceCosumeData p;
ProducerT(ProduceCosumeData p) {
this.p = p; // i am saving the same obj for both threads
}
public void run() {
p.printStringP(10); //it will print 10 times pay
}
}
class ConsumerT extends Thread {
ProduceCosumeData p;
ConsumerT(ProduceCosumeData p) {
this.p = p; // i am saving the same obj for both threads
}
public void run() {
p.printStringC(10); //it will print 10 times tm
}
}
public void test() {
ProduceCosumeData p = new ProduceCosumeData();
ProducerT pt = new ProducerT(p); // with p obj i am creating thread
ConsumerT ct = new ConsumerT(p); // with same p obj i am creating thread
pt.start();
ct.start(); //i am starting 2 threads
}
打印
flag now true
PayprintStringP notify
Waiting in printStringP
Waiting in printStringC
要解决此问题请勿使用等待/通知,除非经验丰富,否则它会被破坏。使用Lock
和Condition
或几乎任何其他java.util.concurrent
类,可以以稳定的方式实现相同的功能。
答案 4 :(得分:-2)
Please find the below code snippet.
package com.java.examples;
public class ProducerConsumer {
public static void main(String[] args) throws InterruptedException {
ProduceCosumeData p = new ProduceCosumeData();
ProducerT pt = new ProducerT(p); // with p obj i am creating thread
ConsumerT ct = new ConsumerT(p); // with same p obj i am creating thread
pt.start();
Thread.sleep(1000);
ct.start(); // i am starting 2 threads
}
}
class ProduceCosumeData {
boolean flag = false;
public synchronized void printStringP(int n) {
for (int i = 0; i < n; i++) {
try {
if (flag) {
notify();
} else
flag = true;
System.out.println("Pay");
if (i <= n - 1) {
wait();
} else {
break;
}
} catch (Exception e) {
System.out.print(e);
}
}
notify();
}
public synchronized void printStringC(int n) {
for (int i = 0; i < n; i++) {
try {
if (flag) {
System.out.println("Tm");
if (i <= n - 1) {
notify();
} else {
break;
}
} else
flag = false;
wait();
} catch (Exception e) {
System.out.print(e);
}
}
}
}
class ProducerT extends Thread {
ProduceCosumeData p;
ProducerT(ProduceCosumeData p) {
this.p = p; // i am saving the same obj for both threads
}
public void run() {
p.printStringP(10); // it will print 10 times pay
}
}
class ConsumerT extends Thread {
ProduceCosumeData p;
ConsumerT(ProduceCosumeData p) {
this.p = p; // i am saving the same obj for both threads
}
public void run() {
p.printStringC(10); // it will print 10 times tm
}
}