Java多线程之过时的suspend 与 resume

2,435 阅读1分钟

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方法先执行导致的错误。

请大家一起抛弃它们。