Java多執行緒之過時的suspend 與 resume

innoyiya發表於2018-01-30

Thread類提供的以下兩個方法:

public final void suspend()

public final void resume()

就像如標題所說的一樣,它們都被Java廢棄了。原因如下:

public class MyThread {
    private static final Object lock = new Object();

    private static class Producer extends Thread{
        Producer() {
            super.setName("producer");
        }
        @Override
        public void run() {
            synchronized (lock) {
                System.out.println("in producer");
                Thread.currentThread().suspend();
                System.out.println("producer is resume");
            }
        }
    }

    private static class Consumer extends Thread {
        Consumer() {
            super.setName("consumer");
        }
        @Override
        public void run() {
            synchronized (lock) {
                System.out.println("in consumer");
                Thread.currentThread().suspend();
                System.out.println("consumer is resume");
            }
        }
    }

    static Producer producer = new Producer();
    static Consumer consumer = new Consumer();

    public static void main(String args[]) throws InterruptedException {
        producer.start();
        //此處是為了讓producer先執行,防止producer的resume先於suspend執行。
        Thread.sleep(2000);
        consumer.start();
        producer.resume();
        consumer.resume();
        producer.join();
        consumer.join();
        System.out.println("All shop");
    }
}
複製程式碼

結果如下:

in producer
producer is resume
in consumer

複製程式碼

此時程式不會退出來,因為consumer執行緒被suspend了。 使用idea的Dump Threads 可以看到執行緒狀態:

"consumer" #13 prio=5 os_prio=0 tid=0x000000002115f800 nid=0x18440 runnable [0x0000000021edf000]
   java.lang.Thread.State: RUNNABLE
	at java.lang.Thread.suspend0(Native Method)
	at java.lang.Thread.suspend(Thread.java:1032)
	at StackAndColumn.MyStack1$Consumer.run(MyStack1.java:28)
	- locked <0x000000076b598638> (a java.lang.Object)

複製程式碼

被suspend掛起的執行緒狀態顯示為"RUNNABLE"狀態,這給排查bug帶來困難性。

從main方法便可以看出,sleep(2000); 是為了防止producer的resume比suspend先執行,所以producer執行緒能夠正確執行。

而consumer退不出是因為main方法在執行consumer.resume();時該執行緒還未獲得鎖資源無法進入同步程式碼塊、尚未執行suspend方法。換言之就是resume方法意外地比suspend方法先執行導致的錯誤。

請大家一起拋棄它們。

相關文章