java多线程暂停与恢复

线程暂停与恢复用suspend()和resume()函数进行操作,下面为使用的实例:

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++;
    }
}

public class Main {
    public static void main(String[] args) {
        Mythread mythread = new Mythread();
        try {
            mythread.start();
            Thread.sleep(5000);
            mythread.suspend();
            System.out.println("A= " + System.currentTimeMillis() +
                    " i=" + mythread.getI());
            Thread.sleep(5000);
            System.out.println("A= " + System.currentTimeMillis() +
                    " i=" + mythread.getI());

            mythread.resume();
            Thread.sleep(5000);

            mythread.suspend();
            System.out.println("B= " + System.currentTimeMillis() +
                    " i=" + mythread.getI());
            Thread.sleep(5000);
            System.out.println("B= " + System.currentTimeMillis() +
                    " i=" + mythread.getI());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

运行的结果如下

A= 1573916447232 i=3989910604
A= 1573916452233 i=3989910604
B= 1573916457233 i=8003591732
B= 1573916462234 i=8003591732

诚然,suspend()和resume()方法的确实现了线程的暂停和恢复。但是也有它的缺点:

1. 独占

在使用suspend和resume方法时,如果使用不当,容易造成公共的同步对象的独占。如在一个有同步锁的方法中让当前线程suspend了,则这个线程就可能永久的suspend了。其他线程无法进入这个同步函数。更要注意某种比较隐晦的场景:

public class Mythread extends Thread{
    private long i = 0;
    @Override
    public void run(){
        while (true)
            i++;
    }
}

public class Main {
    public static void main(String[] args) {
        Mythread mythread = new Mythread();
        try {
            mythread.start();
            Thread.sleep(5000);
            mythread.suspend();
            System.out.println("main end");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

如上线程,可以正确执行并打印出

main end

但是如果把Mythread换成

public class Mythread extends Thread{
    private long i = 0;
    @Override
    public void run(){
        while (true) {
            i++;
            System.out.println(i);
        }
    }
}

线程会一直打印直到suspend,但是不会打印出main end

因为在println方法中,有同步锁。当程序运行到println()方法内部停止时,同步锁没有释放,就会导致当前print方法一直处于暂停的状态,并且锁没有释放,main代码中的System.out.println("main end");不能被打印

2. 不同步

public class MyObject {
    private String username = "1";
    private String password = "11";
    public void setValue(String u, String p) {
        this.username = u;
        if (Thread.currentThread().getName().equals("a")) {
            System.out.println("suspend a thread!");
            Thread.currentThread().suspend();
        }
        this.password = p;
    }
    public void printUP() {
        System.out.println(username + " " + password);
    }
}

public class Main {
    public static void main(String[] args) {
        try {
            MyObject myObject = new MyObject();
            Thread thread = new Thread(){
                public void run() {
                    myObject.setValue("a", "aa");
                }
            };
            thread.setName("a");
            thread.start();
            Thread.sleep(5000);
            Thread thread2 = new Thread(){
                public void run() {
                    myObject.printUP();
                }
            };
            thread2.start();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

运行结果:

thread被suspend了,在thread2执行打印时,打印了password的初始值,造成数据不同步出现不同步的现象。

在线程方法外加个resume,可以让线程恢复,主要要先sleep,保证setValue函数已经调用完suspend

public class Main {
    public static void main(String[] args) {
        try {
            MyObject myObject = new MyObject();
            Thread thread = new Thread(){
                public void run() {
                    myObject.setValue("a", "aa");
                }
            };
            thread.setName("a");
            thread.start();
            // 在调用resume前sleep,保证thread线程已经调用玩suspend,接下来再调用resume
            Thread.sleep(1000);
            thread.resume();
            //Thread.sleep(1000);
            Thread thread2 = new Thread(){
                public void run() {
                    myObject.printUP();
                }
            };
            thread2.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值