在java中,使用suspend()方法暂停线程,使用resume()方法恢复线程的执行。
1.8.1suspend与resume的使用:
线程代码:
public class Thread1 extends Thread {private long i = 0L;public long getI() {return i;}public void setI(long i) {this.i = i;}@Overridepublic void run() {while (true) {i++;}}
}
执行代码:
public class Main {public static void main(String[] args) {try {Thread1 thread = new Thread1();thread.start();Thread.sleep(1000);//A段
thread.suspend();System.out.println("A = " + System.currentTimeMillis() + " I = " +thread.getI());//B段
thread.resume();Thread.sleep(1000);//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.8.2suspend与resume方法的缺点——独占:
在使用suspend与resume方法时,可能会导致公共的同步对象的独占发生,使得其他线程无法访问公共同步对象。
独占代码:
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");}
}
执行代码:
public class Main {public static void main(String[] args) {try {final SynchronizedObject object = new SynchronizedObject();Thread thread1 = new Thread() {@Overridepublic void run() {object.printString();}};thread1.setName("a");thread1.start();Thread.sleep(1000);Thread thread2 = new Thread() {@Overridepublic void run() {System.out.println("因为在Thread1中已经暂停了,后面的语句无法执行,所有只打印了begin");System.out.println("因为此时Thread1已经进入了线程并且锁定了方法printString()所以什么都打不出来");System.out.println("这是死锁的一种表现");object.printString();}};thread2.setName("a");thread2.start();} catch (InterruptedException e) {e.printStackTrace();}}
}
另一种陷阱式的多线程独占问题
线程代码:
public class Thread2 extends Thread {private long i = 0L;@Overridepublic void run() {while (true) {i++;System.out.println(i);}}
}
执行代码:
public class Main {public static void main(String[] args) {try {Thread2 thread = new Thread2();thread.start();Thread.sleep(1000);thread.suspend();System.out.println("main end");} catch (InterruptedException e) {e.printStackTrace();}}
}
执行结果:
卡在数字后面,并没有打印出main end。
原因是在于println()方法,查看其源码会更加清晰:
由源码可以得知,在println内部存在同步锁,当线程在println()内部停止时,同步锁就永远不会释放,就会导致死锁。
1.8.3suspend与resume方法的缺点——不同步:
使用这两个方法容易出现数据不同步的情况。
共享数据类:
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);}
}
执行代码:
public class Main {public static void main(String[] args) {try {final MyObject object = new MyObject();Thread thread = new Thread() {@Overridepublic void run() {object.setValue("a","aa");}};thread.setName("a");thread.start();Thread.sleep(1000);Thread thread1 = new Thread() {@Overridepublic void run() {object.printUsernamePassword();}};thread1.start();} catch (InterruptedException e) {e.printStackTrace();}}
}
执行结果:
源码地址:https://github.com/lilinzhiyu/threadLearning
本文内容是书中内容兼具自己的个人看法所成。可能在个人看法上会有诸多问题(毕竟知识量有限,导致认知也有限),如果读者觉得有问题请大胆提出,我们可以相互交流、相互学习,欢迎你们的到来,心成意足,等待您的评价。