zoukankan      html  css  js  c++  java
  • 使用 suspend 和 resume 暂停和恢复线程

    suspend 和 resume 的使用

    在 Thread 类中有这样两个方法:suspend 和 resume,这两个方法是成对出现的。

    • suspend() 方法的作用是将一个线程挂起(暂停),
    • resume() 方法的作用则是将一个挂起的线程重新开始并继续向下运行。

    通过一个例子来看一下这两个方法的使用:

    public class SuspendThread {
    
        public static void main(String[] args) {
            SimpleDateFormat f = new SimpleDateFormat("HH:mm:ss");
            
            try {
                MyThread2 t = new MyThread2();
                t.start();
                Thread.sleep(1000);
                
                //暂停线程
                t.suspend();
                System.out.println("暂停线程:" + 
                                f.format(System.currentTimeMillis()) + 
                                ", num = " + t.getNum());
                Thread.sleep(5000);
                System.out.println("暂停线程5秒后:" + 
                                f.format(System.currentTimeMillis()) + 
                                ", num = " + t.getNum());
                
                //继续线程
                t.resume();
                System.out.println("--恢复线程--");
                Thread.sleep(5000);
                System.out.println("--恢复线程5秒后--");
                
                //再次暂停线程
                t.suspend();
                System.out.println("再次暂停:" + 
                                f.format(System.currentTimeMillis()) + 
                                ", num = " + t.getNum());
                Thread.sleep(5000);
                System.out.println("再次暂停5秒后:" + 
                                f.format(System.currentTimeMillis()) + 
                                ", num = " + t.getNum());
                
                
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        
    }
    
    class MyThread2 extends Thread{
        private long num = 0;
        
        public void setNum(long num) {
            this.num = num;
        }
        
        public long getNum(){
            return num;
        }
    
        @Override
        public void run() {
            while(true){
                num++;
            }
        }
        
    }
    
    

    输出结果:

    暂停线程:15:27:21, num = 612874824
    暂停线程5秒后:15:27:26, num = 612874824
    --恢复线程--
    --恢复线程5秒后--
    再次暂停:15:27:31, num = 3663392709
    再次暂停5秒后:15:27:36, num = 3663392709
    

    从输出结果打印的时间上看来,线程确实被暂停了,而且还能恢复继续运行。

    为什么弃用?

    虽然现在已经成功的暂停和恢复了线程,但是我们会发现 suspend 和 resume 早已被标注为了废弃方法,并且不推荐使用了。

    不释放锁

    这是因为 suspend 方法不会释放锁,而如果调用了 suspend 方法的目标线程在挂起时对某一重要的系统资源持有锁,那么在目标线程重新开始之前其他任何线程都无法访问该资源。

    public class SynchronizedObject {
    
        public static void main(String[] args) throws InterruptedException {
            
            final SynchronizedObject object = new SynchronizedObject();
            
            Thread thread1 = new MyThread3(object);
            Thread thread2 = new MyThread3(object);
            
            thread1.setName("thread1");
            thread1.start();
            
            Thread.sleep(1000);
            
            thread2.setName("thread2");
            thread2.start();
            
        }
        
        //使用synchronized实现锁功能
        synchronized public void printString(){
            String threadName = Thread.currentThread().getName();
            
            System.out.println(threadName + " - begin");
            if(threadName.equals("thread1")) {
                System.out.println("thread1 - suspend");
                Thread.currentThread().suspend();
            }
            System.out.println(threadName + " - end");
        }
        
        static class MyThread3 extends Thread {
            SynchronizedObject obj;
            
            public MyThread3(SynchronizedObject obj) {
                this.obj = obj;
            }
    
            @Override
            public void run() {
                obj.printString();
            }
        }
    }
    
    

    输出结果:

    thread1 - begin
    thread1 - suspend
    

    从打印的结果来看,虽然 thread2 被启动了,但是并没有进入它的 printString() 方法,这便是因为 printString 方法已经被 thread1 线程锁定并暂定了,导致其他线程无法访问公共代码块。

    不同步

    使用 suspend 和 resume 方法也容易出现因为线程的暂停而导致数据不同步的问题。

    public class TestObject {
    
        public static void main(String[] args) throws InterruptedException {
            final UserObject obj = new UserObject();
            Thread thread1 = new Thread() {
                public void run() {
                    obj.setValue("lisi", "30");
                };
            };
            
            thread1.setName("thread1");
            thread1.start();
            thread1.sleep(500);
            
            Thread thread2 = new Thread(){
                public void run() {
                    obj.printValue();
                };
            };
            
            thread2.start();
            
        }
        
        static class UserObject {
            private String name = "zhangsan";
            private String age = "18";
            
            public void setValue(String name, String age) {
                this.name = name;
                if(Thread.currentThread().getName().equals("thread1")){
                    System.out.println("暂停 thread1");
                    Thread.currentThread().suspend();
                }
                this.age = age;
            }
            
            private void printValue(){
                System.out.println(name + " : " + age);
            }
        }
    
    }
    

    输出结果:

    暂停 thread1
    lisi : 18
    

    程序运行的结果出现了不同步的情况,所以不再建议使用 suspend 和 resume 方法了。

  • 相关阅读:
    Centos 7 zabbix 实战应用
    Centos7 Zabbix添加主机、图形、触发器
    Centos7 Zabbix监控部署
    Centos7 Ntp 时间服务器
    Linux 150命令之查看文件及内容处理命令 cat tac less head tail cut
    Kickstart 安装centos7
    Centos7与Centos6的区别
    Linux 150命令之 文件和目录操作命令 chattr lsattr find
    Linux 发展史与vm安装linux centos 6.9
    Linux介绍
  • 原文地址:https://www.cnblogs.com/liyutian/p/10312767.html
Copyright © 2011-2022 走看看