您的位置:首页 > 编程语言 > Java开发

java多线程suspend、resume暂停与恢复线程

2018-02-28 11:10 393 查看
       今天复习java多线程时,发现一个自己比较陌生的知识点,就是多线程的suspend(暂停线程)和resume(释放线程),虽然这两个方法已经被弃用,但了解一下,也会对多线程更加有深刻的理解吧。
      首先我直接上代码,来看一下,它是如何暂停线程和释放线程的。class MyThread extends Thread{
private long i=0;

public long getI() {
return i;
}

public void setI(long i) {
this.i = i;
}

public void run(){
while(true){
i++;
}
}
}
public class Run{
public static void main(String[] args) {
try {
MyThread thread=new MyThread();
thread.start();//启动线程
Thread.sleep(5000);//主线程挂起
thread.suspend();//thread线程暂停
System.out.println("a="+System.currentTimeMillis()+" i="+thread.getI());//获取系统时间下的i值
Thread.sleep(5000);//主线程挂起
System.out.println("a="+System.currentTimeMillis()+" i="+thread.getI());//获取系统时间下的i值
//很显然以上两者的i值是相同的
thread.resume();//恢复线程
Thread.sleep(5000);
thread.suspend();
System.out.println("B="+System.currentTimeMillis()+" i="+thread.getI());
Thread.sleep(5000);
System.out.println("B="+System.currentTimeMillis()+" i="+thread.getI());
                       /以上两者的i值是相同的,但不同与前面的i值
} catch (InterruptedException e) {
// TODO Auto-generated catch block

e.printStackTrace();
}
System.out.println("end!");

}
}
    通过以上代码,我们就可以发现suspend和resume方法的基本功能。
    那么为什么这两个方法为什么会被弃用呢?我想估计也会有一下两种情况吧。

    1、独占同步对象,导致其他线程无法访问同步对象。
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");

}

}

publicclassRun{

publicstaticvoid main(String[] args) {

try {

final SynchronizedObject object=new SynchronizedObject();

Threadt1=new Thread(){

publicvoid run(){

object.printString();

}

};

t1.setName("a");

t1.start();

Thread.sleep(1000);

Thread t2=new Thread(){

public void run(){

System.out.println("t2启动了,但进入不了printString(),只打印了1个begin");

System.out.println("因为printString方法被a线程锁定并且永远suspend暂停了");

object.printString();
}

};

}catch(InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

System.out.println("end!");

}

}

    在线程t1拿到锁之后,进入被synchronizd修饰的方法时,此时如果调用suspend方法,就会造成t1线程,没有释放锁,而进入暂停的状态,t1就进入一直暂停的状态。t2线程可以启动,但是他却拿不到该锁,因此会发生阻塞。
    另外还有一中情况需要特别注意。class MyThread extends Thread{
private int i=0;
public void run(){
while(true){
i++;
System.out.println(i);
}
}
}
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) {
// TODO Auto-generated catch block

e.printStackTrace();
}
System.out.println("end!");

}
}运行结果没有main end,为什么呢?
这里需要看一下println的源码,println方
4000
法是线程安全的,也就是,在打印前需要难道锁对象,也就是out中的常量public final static PrintStream out = null;此处的out对象就是方法println中使用的锁对象。因为“thread”线程在拿到锁之后,又被suspend,此时thread线程并没有释放锁对象,而当进入主线程的System.out.println("main end");这句时,主线程并拿不到锁对象,而处于阻塞状态,因此才会没有main end的打印。


2、suspend和resume会导致数据不同步的情况。public class Run{
public static void main(String[] args) {
try {
final SynchronizedObject object=new SynchronizedObject();
Thread t1=new Thread(){
public void run(){
object.setValue("a","aa");
}
};
t1.setName("a");
t1.start();
Thread.sleep(1000);
Thread t2=new Thread(){
public void run(){
object.print();
}
};
t2.start();

} catch (InterruptedException e) {
// TODO Auto-generated catch block

e.printStackTrace();
}
System.out.println("end!");

}
}
class SynchronizedObject{
private String userName="l";
private String passWord="ll";
public void setValue(String u,String p){
this.userName=u;
if(Thread.currentThread().getName().equals("a"));
{
System.out.println("停止线程");
Thread.currentThread().suspend();
}
this.passWord=p;
}
public void print(){
System.out.println(userName+" "+passWord);
}

}


从以上可以看出,使用suspend会出现数据不同步的情况。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: