子线程的join方法阻塞主线程,如果在另一个子线程中notify那个子线程,会报监视器状态异常

一.问题

当主线程调用子线程的join方法时,其实还是调用子线程的wait方法来阻塞主线程,那么有两个问题:

a.如果我在另一个子线程中获得当前子线程对象,并调用线程的notify方法,是不是可以解除子线程的阻塞,经测试会报监视器状态异常。

b.子线程是个单独的对象,为啥会阻塞主线程呢?又不存在共享资源竞争,尤其是Thread中join方法是个普通的synchronized方法


二、代码

public class JoinTest {


public static void main(String[] args) throws InterruptedException {

    MyThread3 thread=new MyThread3();

    NotifyThread nt=new NotifyThread(thread);

    thread.start();

    nt.start();

    thread.join();

    for(int i=0;i<3;i++){

        System.out.println(Thread.currentThread().getName() + "线程第" + i + "次执行!");

    }

}

}

class NotifyThread extends Thread{


Thread myThread ;

public NotifyThread(Thread myThread){

    this.myThread=myThread;

}

public void run(){

    try {

        System.out.println("休眠开始");

        Thread.sleep(3000);

        System.out.println("休眠结束");

    } catch (InterruptedException e) {

        // TODO Auto-generated catch block

        e.printStackTrace();

    }

    myThread.notify();

    System.out.println("已唤醒,让Join失效");

}

}


class MyThread3 extends Thread {


@Override

public void run() {

    

    for (int i = 0; i < 10; i++) {

        try {

            System.out.println(this.getName() + "线程第" + i + "次执行!");

            Thread.sleep(1000);

        } catch (InterruptedException e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        }

    }

}

三、异常

Thread-0线程第0次执行!

休眠开始

Thread-0线程第1次执行!

Thread-0线程第2次执行!

休眠结束

Exception in thread "Thread-1" java.lang.IllegalMonitorStateException


at java.lang.Object.notify(Native Method)

at thread.com.simple.NotifyThread.run(JoinTest.java:29)

Thread-0线程第3次执行!

Thread-0线程第4次执行!

Thread-0线程第5次执行!

Thread-0线程第6次执行!

Thread-0线程第7次执行!

Thread-0线程第8次执行!

Thread-0线程第9次执行!

main线程第0次执行!

main线程第1次执行!

main线程第2次执行!


动漫人物
浏览 501回答 1
1回答

湖上湖

先谈为什么“唤醒”不了,notify不会“唤醒”MyThread3,因为阻塞不就是join方法的使命么?再说MyThread3也没有休眠,不是一直在执行么,何来“唤醒”之说!最后来看看join方法的实现,或许对你理解有帮助:public final synchronized void join(long millis) throws InterruptedException {&nbsp; &nbsp; long base = System.currentTimeMillis();&nbsp; &nbsp; long now = 0;&nbsp; &nbsp; if (millis < 0) {&nbsp; &nbsp; &nbsp; &nbsp; throw new IllegalArgumentException("timeout value is negative");&nbsp; &nbsp; }&nbsp; &nbsp; if (millis == 0) {&nbsp; &nbsp; &nbsp; &nbsp; while (isAlive()) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; wait(0);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; while (isAlive()) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; long delay = millis - now;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (delay <= 0) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; wait(delay);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; now = System.currentTimeMillis() - base;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}再来谈为什么有异常,其实已经比较明确了,看注释:/**&nbsp;* Thrown to indicate that a thread has attempted to wait on an&nbsp;* object's monitor or to notify other threads waiting on an object's&nbsp;* monitor without owning the specified monitor.&nbsp;*/当前线程不是该对象monitor所有者时,试图调用其wait或者notify方法就会报这个错,解决异常只要拿到所有者就好了,常见方法:public class NotifyThread extends Thread{&nbsp; &nbsp; Thread myThread ;&nbsp; &nbsp; public NotifyThread(Thread myThread){&nbsp; &nbsp; &nbsp; &nbsp; this.myThread=myThread;&nbsp; &nbsp; }&nbsp; &nbsp; public void run(){&nbsp; &nbsp; &nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; System.out.println("休眠开始");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Thread.sleep(3000);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; System.out.println("休眠结束");&nbsp; &nbsp; &nbsp; &nbsp; } catch (InterruptedException e) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // TODO Auto-generated catch block&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; e.printStackTrace();&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; synchronized(myThread){&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; myThread.notify();&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("已唤醒,让Join失效");&nbsp; &nbsp; }}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java