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

Threads notify not working after wait problem - 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();
    
}


   }

输出是: 车 p

似乎通知有效我最后还想打印汽车但我不知道为什么它不起作用

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

我在同一个 class 中使用了所有方法,我也尝试了单独的 classes 但它没有用

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

有两个问题。一个是您在每个线程中创建单独的对象。 wait 和 notify 调用的对象必须是同一个,被等待的 monitor 就是需要接收 notify 的那个。在此代码中,同步方法在调用方法的实例上使用内部锁。

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

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

添加一个条件变量来记住通知是否发生。

一般来说,模式是在循环中检查条件,参见这个问题:Why we must use "while" for checking race condition not "if"。 post有一个使用变量查看条件是否发生的例子,这里是

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

你做错了几件事。

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

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



public class C {
    boolean ready = false;
    
    public synchronized void test() throws InterruptedException {
        System.out.println("Current thread = " + Thread.currentThread().getName());     
        ready = true;
        System.out.println("car");
        wait();
        System.out.println("car");
    }
    
    public synchronized void Passagier() throws InterruptedException {
        Thread.sleep(4000);
        System.out.println("Current thread = " + Thread.currentThread().getName());
        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 {
                    while(!b.ready) {
                        Thread.sleep(100);
                    }
                    b.Passagier();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        },"t4");
        
        Thread t5 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    b.test();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            
        },"t5");
        System.out.println("Starting t4");
        t4.start();
        System.out.println("Starting t5");
        t5.start();
//      
        t5.join();
        t4.join();
        
    }
    
}

这段代码对我有用我现在有了 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();
    }
   }