暂停线程
暂停线程意味着此线程还可以恢复运行。在Java多线程中,suspend()方法可以暂停线程,resume()方法可以恢复线程。
这两个方法都是已经过时的方法。
1.8.1suspend与resume方法的使用
package cn.zxyy.multiThread.Thread.suspendThread; 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++; } } }
讯享网
讯享网package cn.zxyy.multiThread.Thread.suspendThread; public class MyThreadTest { public static void main(String[] args) { try{ MyThread myThread = new MyThread(); myThread.start(); Thread.sleep(5000);//主线程睡觉5秒,myThread开始运行,计算i的值, myThread.suspend();//然后myThread线程暂停了,主线程睡完5秒后,又开始执行就打印下面的i值 System.out.println("A = " + System.currentTimeMillis() + " i = " +myThread.getI()); Thread.sleep(5000);//打印之后又睡5秒, System.out.println("A = " + System.currentTimeMillis() + " i = " +myThread.getI());//这里我们可以看到i值没有发生变化,说明myThread线程被暂停了 myThread.resume();//使myThread线程恢复运行状态 Thread.sleep(5000);//主线程睡5秒,这时myThread线程在运行 myThread.suspend(); System.out.println("B = " + System.currentTimeMillis() + " i = " +myThread.getI());//再次打印i值发生变化,说明这5秒myThread线程已经被恢复了,并且在运行 Thread.sleep(5000);//主线程再睡5秒,myThread线程被暂停 System.out.println("B = " + System.currentTimeMillis() + " i = " +myThread.getI());//这时再对myThread线程暂停,它又开始不计算值 }catch (InterruptedException e){ e.printStackTrace(); } } }
从运行结果上看,在 主线程休眠的5秒钟内,myThread线程一直在运行,主线程休眠完毕后,调用suspend方法使myThread线程暂停,myThread线程暂停运行。主线程再次休眠5秒,这5秒内,myThread线程还处于暂停状态,直到resume方法被调用,myThread线程才重新开始运行。
1.8.2 suspend与resume方法的缺点----独占
使用suspend方法与resume方法时,如果使用不当,会造成公共的同步对象的独占,使得其他线程无法访问公共的同步对象。
package cn.zxyy.multiThread.Thread.suspendThread; public class SynchronizedObject { synchronized public void printString(){ System.out.println("begin"); if("a".equals(Thread.currentThread().getName())){ System.out.println("a线程永远suspend了"); Thread.currentThread().suspend(); } System.out.println("end"); } }
讯享网package cn.zxyy.multiThread.Thread.suspendThread; public class Run2 { public static void main(String[] args) { try{ final SynchronizedObject synchronizedObject = new SynchronizedObject(); Thread thread1 = new Thread(){ @Override public void run() { synchronizedObject.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("因为thread1拿到了synchronized锁,但是一直没有释放"); synchronizedObject.printString(); } }; thread2.start(); }catch (InterruptedException e){ e.printStackTrace(); } } }

从运行结果上分析,printString方法时同步方法,也就是说该方法的锁对象是当前的object对象,创建多个线程并启动,当a线程开始执行run方法,打印begin后,a线程进入了暂停状态,这时它还在持有锁,并没有释放锁,所以当b线程启动后,进入run方法,可以执行前两句代码,但是等到执行printString方法的时候,由于a线程没有释放锁,所以线程b拿不到锁,无法进入printString方法。
所以同步方法持有锁对象才能进入,上面的方法时我们自己定义的,可以避免,还有一些Java中提供的代码,可能稍不注意,也会导致独占的情况,举个例子,我们先来看下面的代码执行:
public class MyThread2 extends Thread { private int i = 0; @Override public void run() { while(true){ i++; } } }
讯享网package cn.zxyy.multiThread.Thread.suspendThread; public class MyThread2Test { public static void main(String[] args) { try{ MyThread2 thread = new MyThread2(); thread.start(); Thread.sleep(1000); thread.suspend(); System.out.println("main end ");//打印了main end }catch (InterruptedException e){ e.printStackTrace(); } } }


修改代码再次运行:
public class MyThread2 extends Thread { private int i = 0; @Override public void run() { while(true){ i++; System.out.println(i);//如果加上了sout(i),那么就被独占了,因为println方法有synchronized修饰,所以无法释放锁,就不再打印main end了 } } }
从上面两个图看运行结果,为什么左图打印了"main end",而右图没有打印呢?
原因是println方法,看看println方法的源码:

从源码中可以看到,println方法内部是同步代码块,也就是说 当thread线程执行到打印语句时,会拿到一个锁,然后thread线程被暂停了,锁没有释放,主线程也有println方法,它这时候是拿不到锁的,所以这里也会出现独占的问题。
1.8.3 suspend与resume方法的缺点----不同步
讯享网package cn.zxyy.multiThread.Thread.suspendAndResume; public class MyObject { private String username = "1"; private String password = "11"; public void setValue(String u,String p){ this.username = u; if("a".equals(Thread.currentThread().getName())){ System.out.println("a线程永远暂停了"); Thread.currentThread().suspend(); } this.password = p; } public void printUsernamePassword(){ System.out.println(username+" "+password); } }
package cn.zxyy.multiThread.Thread.suspendAndResume; public class MyObjectTest { public static void main(String[] args) { try{ final MyObject obj = new MyObject(); Thread thread1 = new Thread(){ @Override public void run() { obj.setValue("a","aa"); } }; thread1.setName("a"); thread1.start(); Thread.sleep(1000); Thread thread2 = new Thread(){ @Override public void run() { obj.printUsernamePassword(); } }; thread2.start(); }catch (InterruptedException e){ e.printStackTrace(); } } }

从运行结果可以看到,两个线程启动会调用设置值和获取值的方法,出现了脏读的情况,这是因为suspend的方法和resume方法不同步造成的,也就是说当线程a只修改了username的时候,线程b已经运行,获取的值就是新的username,而password还是旧值。
总结:虽然suspend方法和resume方法都已经过时,但是我们需要知道它的缺点:
1.suspend方法暂停线程时,如果有锁的情况不会释放锁,容易造成其他线程无法持有锁,而无法进入run方法。
2.suspend方法和resume方法不是同步方法,可能造成脏读环境。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/43591.html