简体   繁体   English

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

[英]Threads notify not working after wait problem - java

I cannot find The Problem Can Someone Help me.我找不到有人可以帮助我的问题。

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();
    
}


   }

The output is: car p output 是:汽车

it seems like notify is working i want print also car at the last but i donot konw why its not working似乎通知正在工作,我想最后打印汽车,但我不知道为什么它不工作

i hope Someone Help me.我希望有人帮助我。 as soon as possible.尽早。

i have all methodes in the same class and i tried also sepreate classes but it didnt work我在同一个 class 中有所有方法,我也尝试了单独的类,但它没有用

(I am guessing in this case that “it didn't work” means the program hangs. Please be specific about what the issue you're seeing is.) (我猜在这种情况下“它不起作用”意味着程序挂起。请具体说明您看到的问题是什么。)

There are 2 issues.有2个问题。 One is that you are creating separate objects in each thread.一种是您在每个线程中创建单独的对象。 The object that wait and notify are called on have to be the same, the monitor that is waited on is the one that needs to receive the notify.调用wait和notify的object必须是一样的,wait的monitor就是需要接收notify的那个。 In this code the synchronized methods use the intrinsic lock on the instance that the methods are called on.在此代码中,同步方法使用调用方法的实例上的内在锁。

Create the object once in the main method, each thread needs to reference the same object.在main方法中创建一次object,每个线程需要引用同一个object。

The second issue, once you fix the first issue, will be a race condition.第二个问题,一旦你解决了第一个问题,将是一个竞争条件。 If the notify performed by one thread occurs first then when the wait executes the notify has already happened and the wait keeps waiting forever.如果一个线程执行的通知首先发生,那么当等待执行时,通知已经发生并且等待永远等待。

Add a condition variable to remember whether the notify occurred.添加一个条件变量来记住通知是否发生。

In general the pattern is to check the condition in a loop, see this question: Why we must use "while" for checking race condition not "if" .通常,该模式是在循环中检查条件,请参阅这个问题: Why we must use "while" for checks race condition not "if" The post has an example of using a variable to see if a condition occurred, here it该帖子有一个使用变量来查看是否发生条件的示例,here it

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

You're doing several things wrong.你做错了几件事。

  • only start a single instance of C.仅启动 C 的单个实例。 Then use that instance to invoke your methods.然后使用该实例来调用您的方法。 Different instances don't share monitors within synchronized methods不同的实例在同步方法中不共享监视器
  • You're starting two new threads when you start them.当您启动它们时,您正在启动两个新线程。 Just start them as follows:只需按如下方式启动它们:
t4.start();
t5.start();

The primary problem is that t4 starts first and immediately sleeps.主要问题是t4首先启动并立即休眠。 So t5 won't start until the sleep finishes.所以t5在睡眠结束之前不会开始。 But by that time, the notify() for the wait in t4 has been issued before the wait() is invoked in t5 Thus the wait will never see it.但是到那时,在t4中等待的notify()已经在t5中调用wait()之前发出,因此wait永远不会看到它。 So you need to give t4 a chance to start before the sleep occurs.所以你需要在睡眠发生之前给t4一个启动的机会。 There are several ways to fix this.有几种方法可以解决这个问题。 One is to use a flag to signal that the other method is ready.一种是使用标志来表示另一种方法已准备就绪。 But do not use a tight while loop.但不要使用紧密的 while 循环。 Put a sleep inside it for a small amount of time.在里面sleep一小会儿。 I have provided an example below.我在下面提供了一个示例。 I also assigned names to your threads to match your variables.我还为您的线程分配了名称以匹配您的变量。



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();
        
    }
    
}

This Code work for me I have now the while loop这段代码对我有用我现在有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();
    }
   }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM