java多线程:线程的启动和暂停suspend与resume的使用(过期方法)!

1.suspend:挂起,resume:恢复

2.使用suspend()可以将线程挂起,线程处于暂停状态,使用resume()可以将线程恢复运行。

但这两个 API 是过期的,也就是不建议使用的。不推荐使用 suspend() 去挂起线程的原因,是因为 suspend() 在导致线程暂停的同时,并不会去释放任何锁资源。其他线程都无法访问被它占用的锁。直到对应的线程执行 resume() 方法后,被挂起的线程才能继续,从而其它被阻塞在这个锁的线程才可以继续执行。

但是,如果 resume() 操作出现在 suspend() 之前执行,那么线程将一直处于挂起状态,同时一直占用锁,这就产生了死锁。而且,对于被挂起的线程,它的线程状态居然还是 Runnable。

总的来说:在使用suspend()与resume()方法时,如果使用不当,极容易造成公共的同步对象的独占,使得其他线程无法访问公共同步对象。(出现死锁)

3.实例:

package com.springboot.thread;

public class ResumeAndSuspend implements  Runnable{

    private static  long i=0;

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
        while (true){
            i++;
        }
    }

    public static void main(String[] args) {
        try {
            Thread thread  = new Thread(new ResumeAndSuspend());
             // 为了搞清楚当前到底有几个线程 我把线程名字打出来 我们都应该知道 一个java application启动时候主线程必须要启动
            System.out.println(Thread.currentThread().getName());
            //线程一(Thread-0)开始启动
            thread.start();
            //睡眠当前线程(main) 这里着重理解
            // 当我们的主线程睡眠的时候 thread-0 并没有停止 他继续执行 所以在这5s内i一直在增加
            Thread.sleep(5000);
            //线程thread-0 被暂停
            thread.suspend();
            //i is 2509418520
            System.out.println("i is "+ i);
            //睡眠当前线程(main)
            Thread.sleep(5000);
            //i is 2509418520
            //前后两处的i值是一样的 说明我们的thread-0确实被暂停了
            System.out.println("i is "+ i);
            //thred-0 恢复执行 继续做++ 操作
            thread.resume();
            Thread.sleep(5000);
            /*i is 5070468571*/
            System.out.println("i is "+ i);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

运行结果:

注: 这么详细的注释 我太良心了!

我们看截图,显示java application一直处于运行中,所以在次 我们是不是应该想想此时到底有几个线程再执行

首先我们得知我们的thread-0线程resume以后并没有停止他,所以我们可以100%肯定thread-0一定在执行,同时有我们还应该知道一点:在java中,每次程序运行至少创建2个线程。一个是main线程,一个是垃圾回收线程。(面试贼容易问)所以我们可以肯定此时有三个线程在执行,他们分别是GC线程、main线程、thread-0线程。

 

4.问题与思考:在此实例中,当我们的thread-0线程处于suspend状态时,我们再增加一个线程做i++操作,我们的i会增加吗?

像这样:

package com.springboot.thread;

public class ResumeAndSuspend implements  Runnable{

    private static long i=0;

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
        while (true){
            i++;
        }
    }

    public static void main(String[] args) {
        try {
            Thread thread  = new Thread(new ResumeAndSuspend());
            Thread thread1 = new Thread(new ResumeAndSuspend(),"Thread-1");
            // 为了搞清楚当前到底有几个线程 我把线程名字打出来 我们都应该知道 一个java application启动时候主线程必须要启动
            System.out.println(Thread.currentThread().getName());
            //线程一(Thread-0)开始启动
            thread.start();
            //睡眠当前线程(main) 这里着重理解
            // 当我们的主线程睡眠的时候 thread-0 并没有停止 他继续执行 所以在这5s内i一直在增加
            Thread.sleep(5000);
            //线程thread-0 被暂停
            thread.suspend();
            thread1.start();
            //i is 2509418520
            System.out.println("i is "+ i);
            //睡眠当前线程(main)
            Thread.sleep(5000);
            //i is 2509418520
            //前后两处的i值是一样的 说明我们的thread-0确实被暂停了
            System.out.println("i is "+ i);
            //thred-0 恢复执行 继续做++ 操作
            thread.resume();
            Thread.sleep(5000);
            /*i is 5070468571*/
            System.out.println("i is "+ i);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

我们加入了线程一(Thread-1)。

如果我们不是真正的理解suspend与resume的话,我们可能会认为他会占用资源,进而得出i不会增加的结论!

然而,有时候事实却会给你反手一个耳光,打的你啪啪响!

我们看运行结果:

我们可以看到,他们的结果是不一样的,是不是我们了解到的知识是假的呢?

当然不是,在使用suspend()与resume()方法时,如果使用不当,极容易造成公共的同步对象的独占,使得其他线程无法访问公共同步对象。《java多线程编程核心技术》

抓住重点,人家说的是:极容易造成公共的同步对象的独占!(注意,这里是极容易造成独占,并没有说一定会造成独占,所以这是个概率事件,需要很多次试验)

所以我们想要达到预期效果我们应该如何做呢?

代码如下:

package com.springboot.thread;

public class ResumeAndSuspend implements  Runnable{

    private static long i=0;

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
        this.addI();
    }
    
    //保证我们addI是一个同步方法
    synchronized public void addI(){
        while (true){
            i++;
        }
    }

    public static void main(String[] args) {
        try {
            Thread thread  = new Thread(new ResumeAndSuspend(),"Thread-0");
            Thread thread1 = new Thread(new ResumeAndSuspend(),"Thread-1");
            // 为了搞清楚当前到底有几个线程 我把线程名字打出来 我们都应该知道 一个java application启动时候主线程必须要启动
            System.out.println(Thread.currentThread().getName());
            //线程一(Thread-0)开始启动
            thread.start();
            //睡眠当前线程(main) 这里着重理解
            // 当我们的主线程睡眠的时候 thread-0 并没有停止 他继续执行 所以在这5s内i一直在增加
            Thread.sleep(5000);
            //线程thread-0 被暂停
            thread.suspend();
            thread1.start();
            //i is 2509418520
            System.out.println("i is "+ i);
            //睡眠当前线程(main)
            Thread.sleep(5000);
            //i is 2509418520
            //前后两处的i值是一样的 说明我们的thread-0确实被暂停了
            System.out.println("i is "+ i);
            //thred-0 恢复执行 继续做++ 操作
            thread.resume();
            Thread.sleep(5000);
            /*i is 5070468571*/
            System.out.println("i is "+ i);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

运行结果:无!

参考资料:

1.https://www.cnblogs.com/zhengbin/p/6505971.html

2.《java多线程编程核心技术》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值