在java中,使用suspend()方法暂停线程,使用resume()方法恢复线程的执行。
线程代码:
public class Thread1 extends Thread {
private long i = 0L;
public long getI() {
return i;
}
public void setI(long i) {
this.i = i;
}
@Override
public 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();
}
}
}
执行结果:
从执行的时间来看,新开启的线程确实发生了暂停(当前线程暂停与启动的时间与另外开启的线程是一致的),并且能够成功的恢复运行状态。
在使用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() {
@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("因为在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;
@Override
public 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()内部停止时,同步锁就永远不会释放,就会导致死锁。
使用这两个方法容易出现数据不同步的情况。
共享数据类:
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() {
@Override
public void run() {
object.setValue("a","aa");
}
};
thread.setName("a");
thread.start();
Thread.sleep(1000);
Thread thread1 = new Thread() {
@Override
public void run() {
object.printUsernamePassword();
}
};
thread1.start();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
执行结果:
源码地址:https://github.com/lilinzhiyu/threadLearning