如何从另一个线程唤醒线程?

问题描述 投票:0回答:1

为了说明我的问题,在复活节彩蛋时代,这是分镜脚本:第一个字符是时钟,它会定期提供时间。但是此时钟非常令人讨厌:它不会回答询问时间但会定期通知所有观察者的用户,并且此时间段是随机定义的。我的第二个角色是一只压力很大的兔子。除非他知道时间,否则这只兔子什么也做不了。当他完成动作时,他会再次询问时间并等待获取时间,然后再执行其他操作。我可以添加其他字符(一只猫,一个疯狂的帽子制造商...),但是对于此示例,则没有必要。

因此,在Java中,无论观察者的类型如何,我都会有一个观察者可以观察到的时钟;还有一只是观察者的兔子我想保持模式“可观察/观察者”,因为时钟不知道,也不在乎谁是观察者。

这是我正在使用的班级:

时钟

public class Clock implements Runnable, ClockObservable {
    private Long time;

    public Clock () {

    }

    @Override
    public void run() {
        while (true) {
            time=System.currentTimeMillis();
            update();
            try {
                int randomTimeUpdate=(int)( (Math.random() + 1) *500); //This clock will update randomly
                Thread.sleep(randomTimeUpdate);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }   
    }

    @Override
    public void update() {
        for (ClockObserver observer : observers) {
            observer.update(time);
        }       
    }
}

ClockObservable

import java.util.ArrayList;

public interface ClockObservable {
public static ArrayList<ClockObserver> observers = new ArrayList<ClockObserver>();

    public default void addObserver (ClockObserver observer) {
        observers.add(observer);
    }

    public default void resetObservers () {
        observers.clear();
    }

    public void update ();

}

ClockObserver

public interface ClockObserver {

    public void update(Long time);

}

兔子

public class Rabbit implements ClockObserver {

    Long time;

    public Rabbit (Clock clock) {
        clock.addObserver(this);
        whatTimeIsIt();
    }

    public synchronized void whatTimeIsIt () {
        while (true) {
            System.out.println("What time is it ?");
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("It's "+time+" -> Yepeeeee !!!! I can do something before asking the time again...");
            System.out.println("-----------------------------------");
        }
    }

    @Override
    public void update(Long time) {
        this.time=time;
        System.out.println("Time = "+time);
        //How can I notify the rabbit ?
        Rabbit.this.notifyAll(); //This cause a «java.lang.IllegalMonitorStateException»
    }
}

主要

public class Main {

    public static void main(String[] args) {
        Clock clock = new Clock();
        Thread thread = new Thread (clock);
        thread.start();
        new Rabbit(clock);
    }
}

问题是Rabbit类中重写的update方法中的以下指令,该指令生成«java.lang.IllegalMonitorStateException»。

Rabbit.this.notifyAll();

并且,实际上,Rabbit在主线程上,通知在线程0上。

但是,我该怎么办?如何解决我的问题?

谢谢您的所有回答。

Dr_Click

java wait observer-pattern
1个回答
0
投票
public void update(Long time) {
    this.time=time;
    System.out.println("Time = "+time);
    //How can I notify the rabbit ?
    Rabbit.this.notifyAll(); //This cause a «java.lang.IllegalMonitorStateException»
}

notifyAll函数用于通知其他线程某些共享状态已更改。此处共享状态没有更改,因此没有任何通知其他线程的信息。如果您认为this.time是共享状态,请解释为什么不同步的方法修改它而不持有任何锁。您无法使用共享状态来做到这一点。

public synchronized void whatTimeIsIt () {
    while (true) {
        System.out.println("What time is it ?");
        try {
            wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

这里有同样的问题。您在呼叫wait时没有检查您正在等待的事情还没有发生。你在等什么?什么是共享状态,而不是您需要处于的状态?

您不能使用wait,除非等待某些共享状态具有一定的价值。您不能使用notify来通知另一个线程共享状态已更改。

您当前的代码没有任何意义,因为它不等待任何东西,也不通知任何东西。notify/ wait函数不具有Sempahores的语义。他们没有自己的共享状态。您必须实现共享状态。

© www.soinside.com 2019 - 2024. All rights reserved.