Java 如何使用wait/notifyAll

Java 如何使用wait/notifyAll,java,multithreading,wait,runnable,notify,Java,Multithreading,Wait,Runnable,Notify,我想知道在java中是否可能有一个实现Runnable的类,如果该类的一个对象转到wait()(因此线程在收到信号之前停止运行),同一类的另一个对象是否可以通知它继续运行 理想情况下,我希望能够做到的是: public class ThreadClass implements Runnable{ public void run(){ //.. Does some arbitrary work if( aCondition){ //have it wait until somethi

我想知道在java中是否可能有一个实现Runnable的类,如果该类的一个对象转到wait()(因此线程在收到信号之前停止运行),同一类的另一个对象是否可以通知它继续运行

理想情况下,我希望能够做到的是:

public class ThreadClass implements Runnable{

 public void run(){
 //.. Does some arbitrary work

  if( aCondition){  //have it wait until something signals it to contine exection.
 this.wait();
 }

 //Continues to do more work.

 //finished whatever it needed to do. Signal all other threads of this object type to continue their work.
 this.notifyAll();

 }
}
这可能吗?如果可能的话,我会怎么做?我正试图使它,使对象本身可以管理自己和所有其他相同类型的对象。因此,使用这个类的人不必担心如何管理它

我正试图使它,使对象本身可以管理自己和所有其他相同类型的对象。因此,使用这个类的人不必担心如何管理它

如果您想让每个实例都知道每个其他实例,您需要某种类型的静态集合。。。这就使得垃圾收集变得棘手,同时也使得测试变得困难

我建议您使用单独的管理器类型,其唯一任务是管理此类的实例。然后,您仍然只需要在一个地方拥有逻辑,但您不需要知道该类型的所有实例—管理器只需要知道它正在管理什么。您甚至可以创建API,这样客户机代码只需要看到管理器,而单个实例就被隐藏了

编辑:只是澄清一下,您可能根本不需要
wait
/
notifyAll
——更喜欢
java.util.concurrent
中的高级结构,它允许您编写生产者/消费者场景,而无需执行诸如
wait
之类的低级操作。这个答案解决了更高层次的问题,即让对象知道它们应该与哪些其他对象通信。问题的想法是,一种类型的所有对象都知道另一种类型的对象,这将导致问题,因此建议使用manager类

If( condition)
{ wait }

理想情况下,等待应按while条件而不是if块四舍五入。因为客户在继续之前应该确保条件得到满足,而不是仅仅依靠通知

通过管理自身,您可能意味着管理其锁上的同步,并根据某些条件遵守其实例变量的边界

public class ThreadClass implements Runnable {

    public void run() {
        // .. Does some arbitrary work
        synchronized (this) {
            while (! aCondition) { // have it wait until something signals it to
                                // contine exection.
                this.wait();
            }
        }

    /*  Reset the aCondition var to its old value to allow other threads to 
        enter waiting state

        Continues to do more work.

        Finished whatever it needed to do. Signal all other threads of this
         object type to continue their work.*/
        synchronized (this) {
            this.notifyAll();
        }

    }
}
您还应该看看接口。除了使用java.util.concurrent类之外,它似乎有完全相同的需求。这里有一个BoundedBuffer的示例

请参见下面的生产者消费者示例。它具有相同的等待/通知模板。available标志是declare volatile,因此可以对其执行线程安全的读写

public class ProducerConsumerTest {
    public static void main(String[] args) {
        CubbyHole c = new CubbyHole();
        Producer p1 = new Producer(c, 1);
        Consumer c1 = new Consumer(c, 1);

        p1.start();
        c1.start();
    }
}



    class CubbyHole {
        private int contents;
        private volatile boolean available = false;

        public int get() {
            synchronized (this) {
                while (available == false) {
                    try {
                        wait();
                    } catch (InterruptedException e) {
                    }
                }
            }

            available = false;
            synchronized (this) {
                notifyAll();
            }
            return contents;
        }

        public void put(int value) {
            synchronized (this) {
                while (available == true) {
                    try {
                        wait();
                    } catch (InterruptedException e) {
                    }
                }
            }
            available = true;

            contents = value;

            synchronized (this) {
                notifyAll();
            }
        }
    }

    class Consumer extends Thread {
        private CubbyHole cubbyhole;
        private int number;
        private Integer takeSum = new Integer(0);

        public Consumer(CubbyHole c, int number) {
            cubbyhole = c;
            this.number = number;
        }

        public Integer getTakeSum() {
            return takeSum;
        }

        public void run() {
            int value = 0;
            for (int i = 0; i < 100; i++) {
                value = cubbyhole.get();
                takeSum+=value;

            }

            System.out.println("Take Sum for Consumer: " + number + " is "
                    + takeSum);
        }
    }

    class Producer extends Thread {
        private CubbyHole cubbyhole;
        private int number;
        private Integer putSum = new Integer(0);

        public Integer getPutSum() {
            return putSum;
        }

        public Producer(CubbyHole c, int number) {
            cubbyhole = c;
            this.number = number;
        }

        public void run() {
            for (int i = 0; i < 100; i++) {
                int rnd = (int) (Math.random() * 10);
                cubbyhole.put(rnd);
                putSum+=rnd;
                try {
                    sleep((int) (Math.random() * 100));
                } catch (InterruptedException e) {
                }
            }
            System.out.println("Put Sum for Producer: " + number + " is " + putSum);

        }
    }
公共类ProducerConsumerTest{
公共静态void main(字符串[]args){
长方体孔c=新长方体孔();
生产者p1=新生产者(c,1);
消费者c1=新消费者(c,1);
p1.开始();
c1.开始();
}
}
类隔间{
私有int内容;
private volatile boolean available=false;
公共int get(){
已同步(此){
while(可用==false){
试一试{
等待();
}捕捉(中断异常e){
}
}
}
可用=错误;
已同步(此){
notifyAll();
}
返回内容;
}
公开作废认沽权(整数值){
已同步(此){
while(可用==true){
试一试{
等待();
}捕捉(中断异常e){
}
}
}
可用=真实;
内容=价值;
已同步(此){
notifyAll();
}
}
}
类使用者扩展线程{
私人小房间;
私有整数;
私有整数takeSum=新整数(0);
公共消费者(储物间c,整数){
立方孔=c;
这个数字=数字;
}
公共整数getTakeSum(){
返回takeSum;
}
公开募捐{
int值=0;
对于(int i=0;i<100;i++){
value=cubbyhole.get();
takeSum+=值;
}
System.out.println(“为消费者求和:“+number+”是”
+竹森);
}
}
类生成器扩展线程{
私人小房间;
私有整数;
私有整数putSum=新整数(0);
公共整数getPutSum(){
返回putSum;
}
公共制作人(小隔间c,整数){
立方孔=c;
这个数字=数字;
}
公开募捐{
对于(int i=0;i<100;i++){
int rnd=(int)(Math.random()*10);
小隔间放置(rnd);
putSum+=rnd;
试一试{
睡眠((int)(Math.random()*100));
}捕捉(中断异常e){
}
}
System.out.println(“生产者的投入总额:“+number+”是“+putSum”);
}
}
你问过

同一类的另一个对象是否可以通知它继续运行

绝对是如果对象在等待此对象时被阻止,则从任何类的任何实例调用notifyAll将允许它们运行。(包括Runnable本身的等待)

notifyAll不关心它通知的类的类型,它通知等待此对象的任何类。(将其用作锁)

因此,任何类的任何实例都可以对任何对象调用wait或notify。wait和notify是java.lang.Object上的公共方法

请参阅本教程中的“等待、通知”

有关于如何制作的帮助吗