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 方法了。

  • 相关阅读:
    地三鲜
    在linux下使用am335x的DMA
    通过tarball形式安装HBASE Cluster(CDH5.0.2)——集群安装总览
    通过tarball形式安装HBASE Cluster(CDH5.0.2)——如何配置分布式集群中的zookeeper
    如何通过SSH及其Client 批量分发文件和执行管理命令
    解决ESXi有虚拟机模版部署的CentOS虚拟机,网卡eth0找不到问题
    CentOS 65 安装vmware tools 杂记
    安装vmware vCenter Appliance
    使用FileZilla解决从Windows上传文件到Linux vsftpd的乱码问题!
    不关闭seLinux解决vsftpd服务本地用户不能登录问题(500 OOPS: cannot change directory:/home/***)
  • 原文地址:https://www.cnblogs.com/liyutian/p/10312767.html
Copyright © 2011-2022 走看看