同时通知两个线程

时间:2012-11-11 00:16:13

标签: java multithreading notify

如何同时通知线程t1和线程t2(因此与hey 1首先获得hey2的概率相同?我已经尝试过notifyAll,但无法使其正常工作。

class Thr extends Thread
{
    Thr () throws InterruptedException
    {
        Thread t1 = new Thread() {
            public synchronized void run()
            {
                while (true)
                {
                    try {
                        wait();
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }
                    try
                    {
                        Thread.sleep(1500);
                    } catch (Exception e) { }
                    System.out.println("hey 1");
                }
            }
        };

        Thread t2 = new Thread() {
            public synchronized void run()
            {
                while (true)
                {                    
                    try {
                        wait();
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }
                    try
                    {
                        Thread.sleep(1500);
                    } catch (Exception e) { }
                    System.out.println("hey 2");
                }
            }
        };

        t1.start();
        t2.start();
    }

    public static void main(String args[]) throws InterruptedException
    {
        new Thr();
    }
}

4 个答案:

答案 0 :(得分:2)

您应该在共享对象上wait并使用notifyAll,如下所示:

class Thr extends Thread
{
    Thr () throws InterruptedException
    {
        final Object lock = new Object ();

        Thread t1 = new Thread() {
            public void run()
            {
                    try {
                        synchronized (lock) {
                            lock.wait();
                        }
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }

                    System.out.println("hey 1");
            }
        };

        Thread t2 = new Thread() {
            public synchronized void run()
            {
                    try {
                        synchronized (lock) {
                            lock.wait();
                        }
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }

                    System.out.println("hey 2");
            }
        };

        t1.start();
        t2.start();
        synchronized (lock) {
            lock.notifyAll ();
        }
    }

    public static void main(String args[]) throws InterruptedException
    {
        new Thr();
    }
}

答案 1 :(得分:1)

正确的方法是使用notifyAll。您的代码的真正问题似乎是您有两个线程在等待不同互斥锁上的通知。你需要他们等待一个对象......如@ ShyJ的回答所述。


请注意,您无法对此进行编码,以便保证通知首先以相同的概率传递给任一线程:

  • Java线程规范不保证等待/通知的公平性。

  • (通常)在操作系统级别(通常)实现的线程调度程序也没有这样的保证。

重点是应用程序无法控制它。最好的方法是让wait / notifyAll做他们通常做的事情,并设计你的应用程序,这样线程调度中的任何偏差都不会以一种重要的方式影响应用程序的行为。

(FWIW,通常的问题是人们明确地或隐含地假设非随机性......并且当线程以意外的随机顺序进行调度时会被烧毁。)

答案 2 :(得分:0)

我强烈建议避免使用wait / notify并使用更强大的功能。问题是在任何组合中使用wait / notify都可能导致竞争条件。

给予他们学术的同等概率的唯一方法是创建两个Semaphore对象,让线程尝试获取它们,并使用Random来选择哪一个首先发布。即使这样,如果调度程序决定运行第一个尝试获取锁定的程序,那么无论如何,无论Sempahore是否公平,你都会在那里产生偏见。这会强制您等到第一个线程完成后再运行第二个线程,例如通过Thread.join

最重要的是,在并发系统中保证顺序的唯一方法是强制它们采用单线程格式,这样就抛出了让它们首先并发的重点。< / p>

答案 3 :(得分:0)

如果您使用的Java版本大于1.4,那么使用任何concurrent锁将极大地简化您的任务:

java.util.concurrent.locks特别是ReadWrite类型。

现在将消息传递给同一类型的所有线程 - 实现Observer Pattern