等待问题后线程通知不起作用 - java

问题描述

我找不到问题有人可以帮助我。

public class Achterbahn {

private final Object monitor = new Object();

public   synchronized void test() throws InterruptedException {
    
    
        //monitor.wait();
        

        System.out.println("car");
        wait();
        System.out.println("car");
    
}

public  synchronized void Passagier() throws InterruptedException {
    Thread.sleep(2000);

    
        System.out.println("p");

        notify();
    
    //b.t1.notify();
    
    
}
public static void main(String []args) throws InterruptedException {
    

    Thread t4 = new Thread(new Runnable() {

        @Override
        public void run() {
            Achterbahn b = new Achterbahn();
            try {
                b.Passagier();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
        }
        
    });
    Thread t5= new Thread(new Runnable() {
        
        @Override
        public void run() {
            Achterbahn b = new Achterbahn();
            try {
                b.test();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
        }
        
    
    });
    
    
    new Thread(t4).start();
    new Thread(t5).start();     
      t5.join();
      t4.join();
    
}


   }

输出为: 车

似乎通知正在工作,我最后还想打印汽车,但我不知道为什么它不起作用

我希望有人帮助我。尽快。

我在同一个类中有所有方法,我也尝试过单独的类,但没有用

解决方法

(我猜在这种情况下“它不起作用”意味着程序挂起。请具体说明您看到的问题是什么。)

有两个问题。一种是您在每个线程中创建单独的对象。等待和通知被调用的对象必须是相同的,等待的监视器是需要接收通知的监视器。在这段代码中,同步方法在调用方法的实例上使用了内在锁。

在main方法中创建一次对象,每个线程需要引用同一个对象。

第二个问题,一旦你解决了第一个问题,就会成为竞争条件。如果一个线程执行的通知首先发生,那么当等待执行时,通知已经发生并且等待永远等待。

添加条件变量以记住通知是否发生。

通常模式是在循环中检查条件,请参阅此问题:Why we must use "while" for checking race condition not "if"。该帖子有一个使用变量查看条件是否发生的示例,这里是

synchronized(obj)
{
    while (condition_not_matched)
    {
        obj.wait();
    }
    //continue
    dosomething();
}
,

你做错了几件事。

  • 仅启动 C 的单个实例。然后使用该实例调用您的方法。不同的实例在同步方法内不共享监视器
  • 当您启动它们时,您正在启动两个新线程。只需按如下方式启动它们:
t4.start();
t5.start();

主要问题是 t4 首先启动并立即休眠。所以 t5 在睡眠结束之前不会开始。但是到那时,notify() 中等待的 t4 已经之前发出,wait()t5 中被调用 因此 {{1 }} 永远不会看到它。因此,您需要在睡眠发生之前给 wait 一个开始的机会。有几种方法可以解决这个问题。一种是使用标志来表示另一种方法已准备就绪。但不要使用紧凑的 while 循环。将 t4 放入其中一小段时间。我在下面提供了一个例子。我还为您的线程分配了名称以匹配您的变量。

sleep
,

此代码对我有用,我现在有了 while 循环

public class C {

int i = 34;
public synchronized void test() throws InterruptedException {
    System.out.println("car");
    while(i == 34) {
         wait();
    }
   
    notify();
    System.out.println("car");
}

public synchronized void Passagier() throws InterruptedException {
    i = 55;
    System.out.println("p");
    
    notify();
    
}

public static void main(String[] args)
        throws InterruptedException {
    
    C b = new C();
    Thread t4 = new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                b.Passagier();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    });
    Thread t5 = new Thread(new Runnable() {
        
        @Override
        public void run() {
            try {
                b.test();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
        }
        
    });
    
    
   
    t4.start();
    t5.start();
    t4.join();
    t5.join();
    }
   }

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...