《Java多线程编程核心技术》——1.8节暂停线程

    xiaoxiao2023-09-21  152

    本节书摘来自华章社区《Java多线程编程核心技术》一书中的第1章,第1.8节暂停线程,作者高洪岩,更多章节内容可以访问云栖社区“华章社区”公众号查看

    1.8 暂停线程暂停线程意味着此线程还可以恢复运行。在Java多线程中,可以使用suspend()方法暂停线程,使用resume()方法恢复线程的执行。

    1.8.1 suspend与resume方法的使用本节将讲述如何使用suspend与resume方法。创建测试用的项目suspend_resume_test,文件MyThread.java代码如下:

    package mythread; public class MyThread extends Thread { private long i = 0; public long getI() { return i; } public void setI(long i) { this.i = i; } @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(5000); // A段 thread.suspend(); System.out.println("A= " + System.currentTimeMillis() + " i=" + thread.getI()); Thread.sleep(5000); System.out.println("A= " + System.currentTimeMillis() + " i=" + thread.getI()); // B段 thread.resume(); Thread.sleep(5000); // C段 thread.suspend(); System.out.println("B= " + System.currentTimeMillis() + " i=" + thread.getI()); Thread.sleep(5000); System.out.println("B= " + System.currentTimeMillis() + " i=" + thread.getI()); } catch (InterruptedException e) { e.printStackTrace(); } } }

    程序运行后的结果如图1-45所示。从控制台打印的时间上来看,线程的确被暂停了,而且还可以恢复成运行的状态。

    1.8.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-46所示。还有另外一种独占锁的情况也要格外注意,稍有不慎,就会掉进“坑”里。创建测试用的项目suspend_resume_LockStop,类MyThread.java代码如下:

    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-47所示。

    但如果将线程类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-48所示。

    这导致当前PrintStream对象的println()方法一直呈“暂停”状态,并且“锁未释放”,而main()方法中的代码System.out.println("main end!");迟迟不能执行打印。虽然suspend()方法是过期作废的方法,但还是有必要研究它过期作废的原因,这是很有意义的。

    1.8.3 suspend与resume方法的缺点——不同步在使用suspend与resume方法时也容易出现因为线程的暂停而导致数据不同步的情况。创建项目suspend_resume_nosameValue,文件MyObject.java代码如下:

    package myobject; public class MyObject { private String username = "1"; private String password = "11"; public void setValue(String u, String p) { this.username = u; if (Thread.currentThread().getName().equals("a")) { System.out.println("停止a线程!"); Thread.currentThread().suspend(); } this.password = p; } public void printUsernamePassword() { System.out.println(username + " " + password); } } 文件Run.java代码如下: package test; import myobject.MyObject; public class Run { public static void main(String[] args) throws InterruptedException { final MyObject myobject = new MyObject(); Thread thread1 = new Thread() { public void run() { myobject.setValue("a", "aa"); }; }; thread1.setName("a"); thread1.start(); Thread.sleep(500); Thread thread2 = new Thread() { public void run() { myobject.printUsernamePassword(); }; }; thread2.start(); } }

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

    程序运行的结果出现值不同步的情况,所以在程序中使用suspend()方法要格外注意。关于如何解决这些问题,请看后面的章节。

    相关资源:敏捷开发V1.0.pptx
    最新回复(0)