0

如何同时通知 Thread t1 和 Thread t2 (因此获得的概率与第一个相同hey 1hey2?我已经尝试过 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

4 回答 4

2

您应该等待共享对象并使用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();
    }
}
于 2012-11-11T00:28:53.780 回答
1

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


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

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

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

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

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

于 2012-11-11T00:33:32.030 回答
0

如果您使用的 Java 版本高于 1.4,那么使用任何concurrent锁都会大大简化您的任务:

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

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

于 2012-11-11T05:40:14.703 回答
0

我强烈建议避免使用等待/通知并使用更强大的东西。问题是在任何组合中使用等待/通知都可能导致竞争条件。

在学术上给予它们相等概率的唯一方法是创建两个Semaphore对象,让线程尝试获取它们,并使用Random来选择首先释放哪个对象。即便如此,如果调度程序决定运行第一个试图获得锁的调度程序,那么不管是否Sempahore公平,你都会在那里得到偏差。这迫使您等到第一个线程完成后再运行第二个线程,例如 via Thread.join

归根结底,在并发系统中保证顺序的唯一方法是强制它们进入单线程格式,这首先抛弃了让它们并发的全部意义。

于 2012-11-11T00:41:57.323 回答