使用睡眠和中断的Java多线程

时间:2013-01-08 16:14:05

标签: java multithreading synchronization sleep interrupt

class Useless {
    public static boolean b = true;

    public synchronized void u1() {
        try {
            while (b == true)
                wait();
        } catch (InterruptedException i) {
        }
    }

    public synchronized void u2() {
        if (b == true) {
            b = false;
        }
        notify();
    }
}

public class SleepMessages extends Thread {

private Useless u;

    public SleepMessages(Useless u) {
        this.u = u;
    }

    public void run() {
        String importantInfo[] = { "Mares eat oats", "Does eat oats" };
        for (int i = 0; i < importantInfo.length; i++) {
            u.u1();
            System.out.println(importantInfo[i] + " - " + getName());
            try {
                sleep(2000);
            } catch (InterruptedException e) {
            }
        }
    }

    public static void main(String args[]) throws InterruptedException {
        Useless u = new Useless();
        Thread t1 = new SleepMessages(u);
        t1.setName("t1");
        Thread t2 = new SleepMessages(u);
        t2.setName("t2");
        t1.start();
        t2.start();
        sleep(2000);
        System.out.println("Here they go!...");
        t1.interrupt();
        sleep(1000);
        t2.interrupt();
        u.u2();
        sleep(1000);
        u.u2();
    }
}

这个小程序的输出给出: 他们走了!... Mares吃燕麦 - t1 Mares吃燕麦 - t2 吃燕麦 - t2 吃燕麦 - t1

我的问题是为什么线程t2是进入catch的唯一一个(InterruptedException e),为什么结果不是这样的:

他们走了!... Mares吃燕麦 - t1 Mares吃燕麦 - t2 吃燕麦 - t1 吃燕麦 - t2

3 个答案:

答案 0 :(得分:1)

  

我的问题是为什么线程t2是进入catch的唯一一个(InterruptedException e),

我认为t1.interrupt()正在中断run()方法中的睡眠。一旦丢弃了InterruptedException,就无法知道线程在之前被中断了。

  

为什么结果不是这样的:    他们去了!......妈妈吃燕麦 - t1妈妈吃燕麦 - t2吃燕麦 - t1吃燕麦 - t2

Java使用偏向锁定。这意味着获取锁的最后一个线程更有可能首先获得相同的锁。

答案 1 :(得分:0)

只有一个无用的实例,所以只有一个布尔值b。一旦设置为true,SleepMessages的两个实例都可以离开等待循环,无论哪一个都有机会运行,如果有多个CPU同时运行线程,则两者都会出现。

答案 2 :(得分:0)

当我测试你的代码时,两个线程都被中断而没有问题,所以我不确定为什么你认为其中任何一个没有进入catch块。

练习似乎是在第一次使用中断({触发线程打印其第一条消息)时从u1()中的等待中断,并且第二次设置布尔b(触发)第二条消息)。

对于interrupt(),顺序是可以预测的,t1将有足够的时间在主线程在中断之前的第二个睡眠中进行u1()的下一次调用t2

对于u2()部分,订单的可预测性要低得多。 t1t2都在同一台监视器上等待。 notify()电话可能会唤醒任何一个电话。醒来的那个打印出它的第二个消息,睡了一会儿然后停下来。第二个notify()唤醒了在监视器上等待的一个线程。

所以最后两条消息的顺序是不确定的。

最后一些建议:您似乎想要实现的行为可能更容易使用CyclicBarrier实现