如何在Java中通知特定线程 [英] How to notify a specific thread in Java

查看:354
本文介绍了如何在Java中通知特定线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在线程间通信中调用特定线程?

How I can call a particular thread in inter-thread communication?

在下面的程序中,我有两个线程t1t2.

In the program below I have two threads t1 and t2.

当我打电话给t1.notify()时,它会引发:

When I call t1.notify() it raises:

Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
    at java.lang.Object.notify(Native Method)
    at Shared.methodTwo(NotifyThread.java:43)
    at Thread2.run(NotifyThread.java:77)
Error 


class Shared {

    Thread1 t1 ;
    Thread2 t2 ;

    void ThreadInit( Thread1 t1 , Thread2 t2 ) {
        this.t1 = t1 ;
        this.t2 = t2 ;
    }

    synchronized void methodOne()
    {
        Thread t = Thread.currentThread();

        System.out.println(t.getName()+" is relasing the lock and going to wait");

        try
        {
            wait();        //releases the lock of this object and waits
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }

        System.out.println(t.getName()+" got the object lock back and can continue with it's execution");
    }

    synchronized void methodTwo()
    {
        Thread t = Thread.currentThread();

        try
        {
            Thread.sleep(5000);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }

        t1.notify();     

        System.out.println("A thread which is waiting for lock of this object is notified by "+t.getName());
    }
    }

    class Thread1 extends Thread 
    {
    Shared s ;
    Thread1( Shared s ) {

        this.s = s ;
    }

    public void run()
            {
                s.methodOne();   //t1 calling methodOne() of 's' object
            }

    } 

    class Thread2 extends Thread {
         Shared s ;
    Thread2( Shared s ) {

        this.s = s ;

    }

    public void run()
            {
                s.methodTwo();   //t1 calling methodOne() of 's' object
            }


    }
    public class NotifyThread 
    {
    public static void main(String[] args)
    {
        final Shared s = new Shared();

        Thread1 t1 = new Thread1(s) ;
        Thread2 t2 = new Thread2(s) ;

        s.ThreadInit(t1,t2) ;

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

推荐答案

您不/无法通知特定线程.您在锁定对象上调用notify().这将唤醒正在等待锁的线程 1 之一.在您的情况下,锁对象是Thread ...,它会使图片混乱.但是,请参见下文.

You don't / can't notify a specific thread. You call notify() on a lock object. This wakes up one of the threads1 that is waiting on the lock. In your case, the lock object is a Thread ... which rather confuses the picture. However, see below.

但是您的问题(IllegalMonitorStateException)发生是因为进行通知的线程(即 current 线程)没有持有该锁. (硬)要求当前线程在通知锁时必须持有该锁.

But your problem (the IllegalMonitorStateException) happens because the thread doing the notifying (i.e. the current thread) does not hold the lock. It is a (hard) requirement that the current thread must hold the lock when it notifies a lock.

有关更多详细信息,请阅读Object.wait(timeout)的javadocs或(例如)阅读以下内容: http://howtodoinjava.com/core-java/multi-threading/how-to-work-with-wait-notify-and- notifyall-in-java/

For more details, read the javadocs for Object.wait(timeout) or (for example) this: http://howtodoinjava.com/core-java/multi-threading/how-to-work-with-wait-notify-and-notifyall-in-java/

1-如果有多个线程正在等待您的锁,则调度程序将随机"选择一个线程.另外,notifyAll将唤醒所有等待的线程.

我不会将Thread对象用作锁定对象.它可能会起作用,但是也有可能其他事物(可能是运行时系统中的事物)也在锁定/等待/通知Thread对象.这样事情就会变得很混乱.

I would NOT use a Thread object as a lock object. It will possibly work, but there is also a chance that something else (maybe something in the runtime system) is also locking / waiting / notifying the Thread objects. Then things would get very confusing.

(实际上,请阅读

(Indeed, read the javadoc for Thread.join(long) !)

为此目的专门创建锁定对象是更好的选择;例如

It is BETTER to create lock objects specifically for this purpose; e.g.

private final Object lock = new Object();


此外,编写扩展Thread的类通常不是一个好主意.通常最好实现Runnable接口,实例化它,并将实例作为参数传递给Thread构造函数.例如


Also, writing classes that extend Thread is usually a bad idea. It is usually better to implement the Runnable interface, instantiate it, and pass the instance as a parameter to the Thread constructor; e.g.

Thread t = new Thread(new Runnable() {
    public void run() {
        System.out.println("Hello world");
    }});
t.start();

实现Runnable而不是扩展Thread的一个优点是,您可以通过为您管理线程生命周期的东西更轻松地使用代码.例如ExecutorService,fork-join线程池或经典线程池.

One advantage of implementing Runnable rather than extending Thread is that you can use your code more easily with something that manages the thread life cycles for you; e.g. an ExecutorService, a fork-join thread pool or a classic thread pool.

第二个是轻量级线程逻辑可以像匿名类一样简洁地实现.

A second one is that light-weight thread logic can be implemented concisely as an anonymous class ... as in my example.

这篇关于如何在Java中通知特定线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆