【多线程入门系列二】线程的挂起与恢复
2018-03-04 本文已影响34人
5d44bc28b93d

前章回顾
-
多线程入门系列一中我们主要说明了以下知识点
-
线程的三种创建方式,以及其优缺点。分别是继承Thread、实现Runnable接口、以及实现Callable接口
-
线程的启动主要是对比了run方法调用与start方法调用的区别
-
在线程的停止过程中介绍了以下知识点
-
isInterrupted与Interrupted的区别
-
interrupt中断线程的用法
-
sleep前中断与sleep后中断的区别
-
如何优雅的停止线程
-
-
线程的挂起与恢复
在Java中线程的挂起suspend()方法,线程的恢复resume()方法。
-
suspend()与resume()的用法
-
代码实例
public class MyThread extends Thread { @Override public void run() { super.run(); for (int i = 0; i < 500000; i++) { System.out.println(this.getName()+" 运行中" + i); } } } class Run { public static void main(String[] args) { try { MyThread thread = new MyThread(); thread.setName("A"); thread.start(); Thread.sleep(100); thread.suspend(); thread.setName("B"); Thread.sleep(3000); thread.resume(); thread.interrupt(); } catch (InterruptedException e) { e.printStackTrace(); } } }
-
-
分析:
- 从打印结果来看线程确实是先被挂起,让你后重新恢复运行。说明suspend与resume方法确实起到了作用。
-
suspend()与resume()的缺陷--独占
在使用suspend()与resume()方法时极易造成公共资源被独占从而使得其他线程无法访问公共资源。其次如果没有调用suspend()方法直接调用resume()方法是不起作用的。因此这两个方法也不建议使用,被标注为过时方法。
-
代码实例
public class MyThread extends Thread { @Override public void run() { super.run(); int i=0; while (true) { i++; } } } class Run { public static void main(String[] args) { try { MyThread thread = new MyThread(); thread.setName("A"); thread.start(); Thread.sleep(100); thread.suspend(); System.out.println("运行结束"); } catch (InterruptedException e) { e.printStackTrace(); } } }
-
上面例子会打印出运行结束。此时不能证明保持了独占,如果将例子稍微改成下面的方式:
public class MyThread extends Thread { @Override public void run() { super.run(); int i = 0; while (true) { i++; System.out.println(this.getName() + " 运行中" + i); } } } class Run { public static void main(String[] args) { try { MyThread thread = new MyThread(); thread.setName("A"); thread.start(); Thread.sleep(100); thread.suspend(); System.out.println("运行结束"); } catch (InterruptedException e) { e.printStackTrace(); } } }
-
此时并不会打印出"运行结束"字符。原因如下:println()方法是同步的,当线程进入println()方法时获得了同步锁,而此时挂起线程导致同步锁不被释放,所以主线程的println()方法不会执行。这就是独占特性。
-
-
suspend() 与 resume() 的缺陷----不同步
class User{ private String name="123"; private String pwd="****"; public void setValues(String name, String pwd){ this.name = name; if(Thread.currentThread().getName().equals("a")){ Thread.currentThread().suspend(); } this.pwd = pwd; } public void printValues(){ System.out.println("name= " + this.name); System.out.println("pwd= " + this.pwd); } } public class MyThread extends Thread { private User user; public MyThread(User user){ this.user = user; this.setName("a"); } @Override public void run() { super.run(); user.setValues("abc","456"); } } class Run { public static void main(String[] args) { try { User user = new User(); MyThread thread = new MyThread(user); thread.start(); Thread.sleep(1000); user.printValues(); } catch (InterruptedException e) { e.printStackTrace(); } } }
- 通过上面的结果可以看出只有用户名被修改了,而用户密码并未修改,造成了数据的不同步。
-
总结
之所以像stop()、suspend()、resume()等方法之所以被弃用,就是因为他们容易造成无法预料的结果,所以不推荐继续使用