为什么在我的 java 代码中没有调用通知
why is notify not getting called in my java code
这是我的代码:
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 times
但我得到的输出是这样的:
Pay..
接下来是漫长的等待。
以上两个函数在同一个对象中。
为什么通知不释放 wait() 函数?即使我使用 notifyAll(),输出也保持不变。
在 printStringP
的第二次迭代中,属性 flag
为 true
,然后两个线程正在等待。
您在方法中使用了一般wait()
同步。尝试使用对象同步版本,例如 synchronized(this){ wait(); }
然后无论如何,以防止多个线程对同一对象的循环依赖,这对任何多线程程序来说都是非常非常危险的。
或者,更简单地说,在您的 ProducerConsumerData
class 中实现一个适当的 clone()
方法,然后将此对象传递给第一个线程,然后将其克隆传递给下一个线程。尝试在第二个线程的构造函数中使用 p.clone()
而不是 p
。
正如上面的回答,您可以让 printStringP() 的 notify() 只在标志为真时被调用,而不是总是被调用。
这是 classic 的误解,几乎所有尝试使用 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
要解决这个问题 不要使用 wait/notify 除了非常有经验的人之外,它对所有人来说都是坏的。使用 Lock
s 和 Condition
s 或几乎任何其他 java.util.concurrent
class.
可以以稳定的方式实现相同的功能
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
}
}
在您的代码中,您的一个线程正在调用通知,而另一个线程仍未等待。这会导致两个线程都在等待的死锁。
您需要修复同步标志的使用,如果不需要,请不要调用 wait。此外,在 wait() 之后检查锁定条件是否仍然可用是一个好习惯。
这是你的 ProduceConsumeData
class,使用固定标志:
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);
}
}
}
}
这是我的代码:
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 times
但我得到的输出是这样的:
Pay..
接下来是漫长的等待。
以上两个函数在同一个对象中。
为什么通知不释放 wait() 函数?即使我使用 notifyAll(),输出也保持不变。
在 printStringP
的第二次迭代中,属性 flag
为 true
,然后两个线程正在等待。
您在方法中使用了一般wait()
同步。尝试使用对象同步版本,例如 synchronized(this){ wait(); }
然后无论如何,以防止多个线程对同一对象的循环依赖,这对任何多线程程序来说都是非常非常危险的。
或者,更简单地说,在您的 ProducerConsumerData
class 中实现一个适当的 clone()
方法,然后将此对象传递给第一个线程,然后将其克隆传递给下一个线程。尝试在第二个线程的构造函数中使用 p.clone()
而不是 p
。
正如上面的回答,您可以让 printStringP() 的 notify() 只在标志为真时被调用,而不是总是被调用。
这是 classic 的误解,几乎所有尝试使用 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
要解决这个问题 不要使用 wait/notify 除了非常有经验的人之外,它对所有人来说都是坏的。使用 Lock
s 和 Condition
s 或几乎任何其他 java.util.concurrent
class.
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
}
}
在您的代码中,您的一个线程正在调用通知,而另一个线程仍未等待。这会导致两个线程都在等待的死锁。
您需要修复同步标志的使用,如果不需要,请不要调用 wait。此外,在 wait() 之后检查锁定条件是否仍然可用是一个好习惯。
这是你的 ProduceConsumeData
class,使用固定标志:
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);
}
}
}
}