【问题标题】:Java multithreading using sleep and interruptJava多线程使用睡眠和中断
【发布时间】:2012-12-22 13:27:48
【问题描述】:
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();
    }
}

这个小程序的输出给出: 他们来了!... 母马吃燕麦 - t1 母马吃燕麦 - t2 吃燕麦吗 - t2 吃燕麦 - t1

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

他们来了!... 母马吃燕麦 - t1 母马吃燕麦 - t2 吃燕麦 - t1 吃燕麦 - t2

【问题讨论】:

    标签: java multithreading synchronization sleep interrupt


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 我已经做到了,我在run方法上添加了一个system.out.println,如果线程进入了catch,结果就会出现在控制台上,结果是只有线程t2进入了那个catch,t1 也被中断了,但是,它没有进入 catch 并陷入睡眠状态..
    • 你是否在两个 catch 块中添加了一条日志语句,即在 run() 中?
    • 是的,我指的是运行中的 catch 块。只有线程t2进入run方法中的catch块
    • 可以在u1的catch块中添加日志吗?
    • 做了,好像u1中只有线程t1进入catch块,所以基本上每个线程进入不同的catch块,这是为什么呢?
    【解决方案2】:

    Useless 只有一个实例,所以只有一个布尔值 b。一旦将其设置为 true,两个 SleepMessages 实例都可以离开等待循环,因此,如果有多个 CPU 同时运行线程,则无论哪一个碰巧有机会运行,或者两者都将退出。

    【讨论】:

      【解决方案3】:

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

      练习似乎是在第一次使用中断(触发线程打印其第一条消息)并第二次设置布尔值b(触发第二条消息)来打破u1() 中的等待.

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

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-02-11
        • 2018-08-09
        • 1970-01-01
        • 2014-07-29
        • 2014-06-07
        • 2019-05-24
        • 2011-05-14
        • 2011-11-10
        相关资源
        最近更新 更多