Java 线程示例-等待()之前通知()?

Java 线程示例-等待()之前通知()?,java,multithreading,Java,Multithreading,我有以下线程示例: class TickTock { String state; // contains the state of the clock synchronized void tick(boolean running) { if(!running) { // stop the clock state = "ticked"; notify(); // notify any waiting threads

我有以下线程示例:

class TickTock {
    String state; // contains the state of the clock

    synchronized void tick(boolean running) {
        if(!running) { // stop the clock 
            state = "ticked";
            notify(); // notify any waiting threads 
            return;
        }
        System.out.print("Tick ");
        state = "ticked"; // set the current state to ticked
        notify(); // let tock() run 
        try {
            while(!state.equals("tocked"))
                wait(); // wait for tock() to complete 
        }
        catch(InterruptedException exc) {
            System.out.println("Thread interrupted.");
        }
    }

    synchronized void tock(boolean running) {
        if(!running) { // stop the clock 
            state = "tocked";
            notify(); // notify any waiting threads 
            return;
        }
        System.out.println("Tock");
        state = "tocked"; // set the current state to tocked
        notify(); // let tick() run 
        try {
            while(!state.equals("ticked"))
                wait(); // wait for tick to complete 
        }
        catch(InterruptedException exc) {
            System.out.println("Thread interrupted.");
        }
    }
}

class MyThread implements Runnable {
    Thread thrd;
    TickTock ttOb;

    // Construct a new thread. 
    MyThread(String name, TickTock tt) {
        thrd = new Thread(this, name);
        ttOb = tt;
        thrd.start(); // start the thread 
    }

    // Begin execution of new thread. 
    public void run() {

        if(thrd.getName().compareTo("Tick") == 0) {
            for(int i=0; i<5; i++) ttOb.tick(true);
            ttOb.tick(false);
        }
        else {
            for(int i=0; i<5; i++) ttOb.tock(true);
            ttOb.tock(false);
        }
    }
}

class ThreadCom {
    public static void main(String args[]) {
        TickTock tt = new TickTock();
        MyThread mt1 = new MyThread("Tick", tt);
        MyThread mt2 = new MyThread("Tock", tt);

        try {
            mt1.thrd.join();
            mt2.thrd.join();
        } catch(InterruptedException exc) {
            System.out.println("Main thread interrupted.");
        }
    }
}
类滴答声{
字符串状态;//包含时钟的状态
同步空勾号(布尔运行){
如果(!运行){//停止时钟
state=“勾选”;
notify();//通知所有等待的线程
返回;
}
系统输出打印(“勾选”);
state=“ticked”;//将当前状态设置为ticked
notify();//让tock()运行
试一试{
而(!state.equals(“tocked”))
wait();//等待tock()完成
}
捕获(中断异常exc){
System.out.println(“线程中断”);
}
}
同步的void tock(布尔运行){
如果(!运行){//停止时钟
state=“tocked”;
notify();//通知所有等待的线程
返回;
}
系统输出打印项次(“Tock”);
state=“tocked”;//将当前状态设置为tocked
notify();//让tick()运行
试一试{
而(!state.equals(“勾选”))
wait();//等待勾号完成
}
捕获(中断异常exc){
System.out.println(“线程中断”);
}
}
}
类MyThread实现可运行{
螺纹螺纹;
滴答滴答;
//构造一个新线程。
MyThread(字符串名,滴答滴答){
thrd=新线程(此,名称);
ttOb=tt;
thrd.start();//启动线程
}
//开始执行新线程。
公开募捐{
if(thrd.getName().compareTo(“勾选”)==0){
对于(int i=0;i
mt2是如何等待mt1的

mt2
将状态设置为“tocked”后,它将等待直到变为“ticked”。只有
mt1
可以这样做

这是因为mt1是在mt2之前创建的,因此首先进入同步方法吗

哪一个线程首先进入方法并不重要。如果需要,每个线程都会等待另一个线程。如果可以向前推进的线程首先获得锁,它就会向前推进。如果错误的线程获得锁,它只会等待另一个线程,释放锁,并允许该线程向前推进

如果是-下一个问题是:为什么mt1在wait()之前调用notify()

由于
mt
已经更改了
状态
,而另一个线程可能正在等待状态的更改,因此调用
notify
非常重要。首先调用
wait
将是一场灾难——另一个线程可能正在等待此线程所做的更改的通知,而两个线程互相等待则是一场灾难艾德洛克

如何在不调用wait()的情况下释放监视器


不可能。但这没关系。当监视器完全完成或等待另一个线程时,线程将释放监视器。在所有其他情况下,它会主动修改共享状态,您不希望释放锁。

我用简单的程序启动线程。我用同步方法创建了类。此方法s由两个或多个线程执行,我知道该方法需要同步,因为两个线程同时使用它。现在我有一个对象和两个不同的方法-那么为什么它们需要同步?你能解释一下在两个首次打印中发生了什么吗?我很困惑,因为我认为两个线程都进入了tick()和tock()同时进行,所以前两个打印(“tick-tock”)只是关于命令顺序的问题,因为当您输入方法时,tick()和ottack()中都没有关于线程执行的控制。因此,System.out.println(tick/tack)可以在线程进入时执行。为什么在每个线程执行自己的方法时mt1或mt2需要互相等待?@vviston代码的目的是演示如何处理线程到达某个点时,在另一个线程到达某个点之前无法向前进行的情况。我意识到我在h理解只有一个线程同时执行同步方法的概念。我认为两个线程可以使用相同的对象方法,但根据Oracle,当on thread执行对象的一个方法时,对象被完全锁定。我不知道这一点。