通知并等待代码方案

时间:2017-06-09 06:32:51

标签: java multithreading wait notify

public class NotifyAndWaitExample2 {
    static int i = 0;

    public static void main(String[] args) {
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (this) {
                    if (i <= 0) {
                        System.out.println("i=" + i + "in t1");
                        System.out.println(Thread.currentThread().getName() + "is running");
                        try {
                            wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println(Thread.currentThread().getName() + "is waken up");
                }
            }
        });
        Thread t4 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (this) {
                    i++;
                    System.out.println("i=" + i + "in t4");
                    System.out.println(Thread.currentThread().getName() + "is notifying");
                    try {
                        Thread.sleep(1000);
                        notify();
                        System.out.println("notified");
                    } catch (InterruptedException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }
                }
            }
        });
        t1.start();
        t4.start();
    }
}

这里显示了ouptut: -

i=0in t1 
i=1in t4 
Thread-0is running 
Thread-1is notifying 
notified 

最后一行也应印在输出中,即; &#34; Thread-0 is waken up&#34 ;.为什么在印刷后通知&#34;&#34;它没有松散锁定线程&#34; t1 run()方法&#34;并在t1中的wait()之后继续执行代码。即它应该打印&#34;线程0被唤醒&#34;印刷后#34;通知&#34;。

4 个答案:

答案 0 :(得分:2)

您的synchronized块有“无”效果。

您的synchronized(this)只获取Runnable实例的锁定,您还可以在其中实施run方法。

您的主题t1将永远不会收到通知,它会等待您使用Runnable方法的wait()获得通知。保存对此Runnable的引用的唯一对象是Thread对象t1,并且(通常)不会在该Runnable上调用notify()notifyAll()

我使用int[]来存储int值以及持有锁/监视器。解决方案只是向您展示如何做到这一点,并不意味着这样做是很好的做法。

我建议阅读一篇关于Java中的同步如何工作的好教程。

我已经修改了你的示例,以便它按预期工作。

public class NotifyAndWaitExample2 {
    private static int[] i = {0};

    public static void main(String[] args) {
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (i) {
                    if (i[0] <= 0) {
                        System.out.println("i=" + i[0] + " in t1");
                        System.out.println(Thread.currentThread().getName() + " is running");
                        try {
                            i.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println(Thread.currentThread().getName() + " is waken up");
                }
            }
        });
        Thread t4 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (i) {
                    i[0]++;
                    System.out.println("i=" + i[0] + "in t4");
                    System.out.println(Thread.currentThread().getName() + " is notifying");
                    try {
                        Thread.sleep(1000);
                        i.notifyAll();
                        System.out.println("notifying");
                    } catch (InterruptedException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }
                }
            }
        });
        t1.start();
        t4.start();
    }
}

答案 1 :(得分:1)

你锁定了两个不同的对象。在您的示例中,“this”指的是每个可运行的实例。除此之外,变量“i”必须是易失性的(否则,不同的线程将不会看到最新的变化)

见下文:

public class NotifyAndWaitExample {

    private volatile int i = 0;
    private Object lock1 = new Object();

    public static void main(String[] args) {
        NotifyAndWaitExample notifyAndWaitExample = new NotifyAndWaitExample();
        notifyAndWaitExample.execute();
    }

    private void execute() {


        Thread t1 = new Thread(new Runnable() {

            @Override
            public void run() {
                synchronized (lock1) {
                    if (i <= 0) {
                        System.out.println("i= " + i + " in t1");
                        System.out.println(Thread.currentThread().getName() + " is running");

                        try {
                            lock1.wait();

                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println(Thread.currentThread().getName() + " is waken up");
                }
            }
        });

        Thread t4 = new Thread(new Runnable() {

            @Override
            public void run() {
                synchronized (lock1) {
                    i++;
                    System.out.println("i= " + i + " in t4");
                    System.out.println(Thread.currentThread().getName() + " is notifying");
                    try {
                        Thread.sleep(1000);
                        lock1.notify();
                        System.out.println("notified");
                    } catch (InterruptedException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }
                }
            }
        });


        t1.start();
        t4.start();
    }

}

答案 2 :(得分:1)

public class NotifyAndWaitExample2 {
    static int i = 0;

    public static void main(String[] args) {
        Object lock = new Object();
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lock) {
                    if (i <= 0) {
                        System.out.println("i=" + i + "in t1");
                        System.out.println(Thread.currentThread().getName() + "is running");
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println(Thread.currentThread().getName() + "is waken up");
                }
            }
        });
        Thread t4 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lock) {
                    i++;
                    System.out.println("i=" + i + "in t4");
                    System.out.println(Thread.currentThread().getName() + "is notifying");
                    try {
                        Thread.sleep(1000);
                        lock.notify();
                        System.out.println("notified");
                    } catch (InterruptedException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }
                }
            }
        });
        t1.start();
        t4.start();
    }
}

答案 3 :(得分:1)

您当前的问题是您在错误的(不同的)对象上进行同步。正如您在代码中所说的“synchronized(this)”,“this”是当前的线程实例。因为你有两个同步不会发生。

我真的建议在监视器中思考。监视器是一个ressource包装器,它以一种保持内部状态一致性的方式限制并发访问。我重新制定了你的代码以使用监视器。

public class NotifyAndWaitExample2 {

    private static class Monitor {

        // Resource
        private int i;


        public synchronized void operation1() {

            if (i <= 0) {
                System.out.println("i=" + i + "in t1");
                System.out.println(Thread.currentThread().getName() + "is running");
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName() + "is waken up");

        }


        public synchronized void operation2() {

            i++;
            System.out.println("i=" + i + "in t4");
            System.out.println(Thread.currentThread().getName() + "is notifying");
            try {
                Thread.sleep(1000);
                notify();
                System.out.println("notified");
            } catch (InterruptedException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }

        }

    }

    public static void main(String[] args) {

        Monitor monitor = new Monitor();

        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                monitor.operation1();
            }
        });

        Thread t4 = new Thread(new Runnable() {
            @Override
            public void run() {
                monitor.operation2();
            }
        });

        t1.start();
        t4.start();

    }
}

“wait()”和“notify()”现在在SAME对象上执行,因此执行的线程将被同步。