《Java多线程编程核心技术(第2版)》 —1.12.2 suspend()方法与resume()方法的缺点—独占

举报
华章计算机 发表于 2020/02/08 15:30:50 2020/02/08
【摘要】 本节书摘来自华章计算机《Java多线程编程核心技术(第2版)》 一书中第1章,第1.12.2节,作者是高洪岩。

1.12.2 suspend()方法与resume()方法的缺点—独占

如果suspend()方法与resume()方法使用不当,极易造成公共同步对象被独占,其他线程无法访问公共同步对象的结果。

创建suspend_resume_deal_lock项目,文件SynchronizedObject.java代码如下:

package testpackage;

 

public class SynchronizedObject {

 

    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 test.run;

 

import testpackage.SynchronizedObject;

 

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()方法!只打印1个begin");

                    System.out.println("因为printString()方法被a线程锁定并且永远suspend暂停了!");

                    object.printString();

                    }

            };

            thread2.start();

        } catch (InterruptedException e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        }

    }

 

}

程序运行结果如图1-55所示。

另外一种独占锁的情况也需要格外注意,稍有不注意,就会掉进“坑”里。创建测试用的项目suspend_resume_LockStop,类MyThread.java代码如下:

 image.png

图1-55 独占并锁死printString()方法

package mythread;

 

public class MyThread extends Thread {

    private long i = 0;

 

    @Override

    public void run() {

        while(true) {

            i++;

        }

    }

}

类Run.java代码如下:

package test.run;

 

import mythread.MyThread;

 

public class Run {

 

    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();

        }

    }

 

}

程序运行结果如图1-56所示。

image.png

进程状态在控制台中呈红色按钮显示,说明进程并未销毁。虽然main线程销毁了,但是MyThread呈暂停状态,所以进程不会销毁。

但如果将线程类MyThread.java更改如下:

package mythread;

 

public class MyThread extends Thread {

    private long i = 0;

 

    @Override

    public void run() {

        while (true) {

            i++;

            System.out.println(i);

        }

    }

}

再次运行程序,控制台不输出main end,如图1-57所示。

 image.png

图1-57 不输出main end信息

出现这种情况的原因是当程序运行到System.out.println(i)方法内部停止时,同步锁是不释放的,println()方法源代码如图1-58所示。

 image.png

图1-58 锁不释放

当前PrintStream对象的println()方法一直呈“暂停”状态,并且“锁未释放”,而main()方法中的代码“System.out.println("main end!");”也需要这把锁,main线程并未销毁,造成迟迟不能输出main end。

虽然suspend()方法是过期作废的方法,但研究其过期作废的原因是很有必要的。


【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。