`
atell
  • 浏览: 158673 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

wait时间到或被中断唤醒时,仍然需要等待获取锁。

阅读更多
import java.io.IOException;

public class Demo {

    /**
     * @param args
     * @throws IOException
     * @throws InterruptedException
     * @throws ClassNotFoundException
     */
    public static void main(String[] args) throws IOException, InterruptedException, ClassNotFoundException {
        
        T1 t1 = new T1();
        T2 t2 = new T2(t1);
        t1.start();
        t2.start();
        
    }


    static Integer i = 0;

    static class T1 extends Thread {

        public void run() {

            synchronized (i) {
                System.out.println("T1-在syn里");
                try {
                    i.wait(50L);//验证表明:wait时间到或被中断唤醒,不会继续执行或者跳到catch里
                                // (因为根本得不到执行,根本没法抛出InterruptedException,所以即使catch块放在syschronized外也一样 ),
                                //而是还需要等待获得锁。
                                //如果wait时间到或被中断唤醒,而T2还在syn里,那么T1还是会等待。
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("结束wait-T1");
                System.out.println("T1-在syn里");
                try {
                    Thread.sleep(10000L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("T1-在syn里");
            }
            System.out.println("离开syn-T1");

        }
    }
    

    static class T2 extends Thread {

        Thread t1;
        public T2(Thread t1){
            this.t1 = t1;
        }
        
        public void run() {
            synchronized (i) {
                System.out.println("T2-在syn里");
                try {
                    t1.interrupt();
                    Thread.sleep(10000L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("T2-还在syn里");
            }
            System.out.println("T2-离开syn");

        }
    }
}

 

验证表明: wait时间到或被中断唤醒,不一定会继续执行或者跳到catch里,而是还需要等待获得锁。
               如果wait时间到或被中断唤醒,而T2还在syn里,那么T1还是会等待。

 

另外,Thread.interrupt()唤醒线程之后,其实是设置了Thead的中断状态,后续任何时候,当该线程尝试wait,join,sleep时,中断状态都会起作用,使得Thread被中断,wait/join/sleep方法会抛出中断异常(wait需要获取锁后才能继续抛出异常)。这点javadoc有说明。

 

 

_____________________________________________________________________________

 

 

 

package com.atell;

import java.io.IOException;

public class Demo {

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

        T1 t1 = new T1();
        T2 t2 = new T2(t1);
        t1.start();
        t2.start();

    }

    static Integer i = 0;

    static class T1 extends Thread {

        public void run() {

            synchronized (i) {
                System.out.println("T1-syn-start");
                try {
                    i.wait();// 可以被notify唤醒,也可以被interrupt唤醒,取决于T2中哪个操作先执行
                } catch (InterruptedException e) {
                    System.out.println("在wait时被中断");
                }
                try {
                    Thread.sleep(2000L);
                } catch (InterruptedException e) {
                    System.out.println("在sleep时被中断");
                }
                System.out.println("T1-syn-end");
            }
            System.out.println("离开syn-T1");

        }
    }

    static class T2 extends Thread {

        Thread t1;

        public T2(Thread t1){
            this.t1 = t1;
        }

        public void run() {
            synchronized (i) {
                System.out.println("T2-syn-start");
                //(1)如果先interrupt再notify,那么i.wait会因为interrupt而醒过来,notify则不对它起作用(如果此时Monitor的等待队列有其他线程,则notify必须去唤醒其他线程,不能虚发- Java语言规范17.8.4最后一句明确提到。)。
                //t1.interrupt();
                //i.notify();
                //(2)如果先notify再interrupt,那么i.wait会因为notify而醒过来,interrupt则对T1后续的sleep起作用。
                i.notify();
                t1.interrupt();
                System.out.println("T2-syn-end");
            }
            System.out.println("T2-离开syn");

        }
    }
}

 

验证表明: wait可以被notify唤醒,也可以被interrupt唤醒,取决于哪个操作先执行

(以上是看《Java语言规范17.8节》之后的结论)

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics