Java多线程问题--suspend()和resume()独占问题

本文内容部分引自《Java多线程编程核心技术》,感谢作者!!!

代码地址:https://github.com/xianzhixianzhixian/thread.git

为什么线程暂停不用suspend()和resume()了?因为这两个方法有独占和不同步的问题,先说说“独占”

1、线程内部调用suspend()方法却未调用resume()导致的对象锁独占情况,原因在程序备注里

SynchronizedObject.java

package thread.suspend.resume.deallock;

/**
 * 测试suspend和resume的缺点--独占
 * 原因是当前线程主动暂停,也只能由Thread.currentThread().resume()来恢复运行
 * 但是在线程外别的线程没有办法让该线程恢复运行,所以该线程一直处于suspend状态,且占用了object对象的锁,不释放
 * @author: xianzhixianzhixian
 * @date: 2018-12-11 19:35
 */
public class SynchronizedObject {

    /**
     * 方法锁
     * synchronized 方法锁控制对类成员变量的访问:
     * 每个类实例对应一把锁
     * 每个synchronized方法都必须获得调用该方法的类实例的”锁“方能执行,否则所属线程阻塞。
     */
    synchronized public void printString(){
        System.out.println("begin");
        if (Thread.currentThread().getName().equals("a")){
            System.out.println("a线程永远suspend了!");
            Thread.currentThread().suspend();
        }
        System.out.println("end");
    }
}

Run.java

package thread.suspend.resume.deallock;

/**
 * @author: xianzhixianzhixian
 * @date: 2018-12-11 19:38
 */
public class Run {

    public static void main(String[] args) {
        try {
            final SynchronizedObject object = new SynchronizedObject();
            Thread thread1 = new Thread(){
                @Override
                public void run(){
                    object.printString();
                }
            };
            thread1.setName("a");
            thread1.start();
            Thread.sleep(1000);
            Thread thread2 = new Thread(){
                @Override
                public void run(){
                    System.out.println("thread2启动了,但是进入不了printString()方法!");
                    System.out.println("因为printString()方法被a线程锁定并且永远suspend暂停了!");
                    object.printString();
                }
            };
            thread2.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

运行结果:

Java多线程问题--suspend()和resume()独占问题_第1张图片

2、线程run()函数内部调用了System.out.println();并且在别的线程中调用了该线程的suspend()方法

MyThread.java

package thread.suspend.resume.deallock;

/**
 * suspend()和System.out.println()导致的独占问题
 * @author: xianzhixianzhixian
 * @date: 2018-12-11 20:12
 */
public class MyThread extends Thread {

    private long i=0;
    @Override
    public void run() {
        super.run();
        while (true){
            i++;
            System.out.println(i);
        }
    }
}

MyThreadRun.java

package thread.suspend.resume.deallock;

/**
 * 独占的原因是因为PritStream对象的println()方法一直呈暂停状态,并且锁未释放
 * 别的线程无法获得PritStream对象锁导致一直暂停
 * @author: xianzhixianzhixian
 * @date: 2018-12-11 20:13
 */
public class MyThreadRun {

    public static void main(String[] args) {
        try {
            MyThread thread = new MyThread();
            thread.start();
            Thread.sleep(1000);
            thread.suspend();
            System.out.println("main end!");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

运行结果:程序一直处于暂停状态,"main"字符串无法输出

Java多线程问题--suspend()和resume()独占问题_第2张图片

下面来解释原因:

看看System.out究竟是什么,是System的一个对象

Java多线程问题--suspend()和resume()独占问题_第3张图片

而System.out.println()方法呢,是一个同步的方法?

Java多线程问题--suspend()和resume()独占问题_第4张图片

每当调用System.out.println()方法时,该方法会获得this也就是PrintStream对象的锁(System.out)。而在第二个例子中run()方法中含有System.out.println()方法,当调用thread.suspend()方法时该线程暂停并且未释放PrintStream对象锁,导致main线程无法获得PrintStream对象锁,一直无法输出"main"字符串!

你可能感兴趣的:(Java,多线程)