zoukankan      html  css  js  c++  java
  • 1.8暂停线程

    在java中,使用suspend()方法暂停线程,使用resume()方法恢复线程的执行。

    1.8.1suspend与resume的使用:

    线程代码:

    public class Thread1 extends Thread {
        private long i = 0L;
    
        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) {
            try {
                Thread1 thread = new Thread1();
                thread.start();
                Thread.sleep(1000);
                //A段
                thread.suspend();
                System.out.println("A = " + System.currentTimeMillis() + " I = " +thread.getI());
                //B段
                thread.resume();
                Thread.sleep(1000);
                //C段
                thread.suspend();
                System.out.println("B = " + System.currentTimeMillis() + " I = " + thread.getI());
                Thread.sleep(5000);
                System.out.println("B = " + System.currentTimeMillis() + "I = " + thread.getI());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    执行结果:

    从执行的时间来看,新开启的线程确实发生了暂停(当前线程暂停与启动的时间与另外开启的线程是一致的),并且能够成功的恢复运行状态。

    1.8.2suspend与resume方法的缺点——独占:

    在使用suspend与resume方法时,可能会导致公共的同步对象的独占发生,使得其他线程无法访问公共同步对象。

    独占代码:

    public class SynchronizedObject {
        synchronized public void printString() {
            System.out.println("begin");
            if ("a".equals(Thread.currentThread().getName())) {
                System.out.println("a线程永远的暂停了,suspend");
                Thread.currentThread().suspend();
            }
            System.out.println("end");
        }
    }

    执行代码:

    public class Main {
        public static void main(String[] args) {
            try {
                final SynchronizedObject object = new SynchronizedObject();
                Thread thread1 = new Thread() {
                    @Override
                    public void run() {
                        object.printString();
                    }
                };
                thread1.setName("a");
                thread1.start();
                Thread.sleep(1000);
                Thread thread2 = new Thread() {
                    @Override
                    public void run() {
                        System.out.println("因为在Thread1中已经暂停了,后面的语句无法执行,所有只打印了begin");
                        System.out.println("因为此时Thread1已经进入了线程并且锁定了方法printString()所以什么都打不出来");
                        System.out.println("这是死锁的一种表现");
                        object.printString();
                    }
                };
                thread2.setName("a");
                thread2.start();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    另一种陷阱式的多线程独占问题

    线程代码:

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

    执行代码:

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

    执行结果:

    卡在数字后面,并没有打印出main end。

    原因是在于println()方法,查看其源码会更加清晰:

    由源码可以得知,在println内部存在同步锁,当线程在println()内部停止时,同步锁就永远不会释放,就会导致死锁。  

    1.8.3suspend与resume方法的缺点——不同步:

    使用这两个方法容易出现数据不同步的情况。

    共享数据类:

    public class MyObject {
        private String username = "1";
        private String password = "11";
        public void setValue(String u,String p) {
            this.username = u;
            if("a".equals(Thread.currentThread().getName())) {
                System.out.println("停止a线程");
                Thread.currentThread().suspend();
            }
            this.password = p;
        }
        public void printUsernamePassword() {
            System.out.println(username + "|||" + password);
        }
    }

    执行代码:

    public class Main {
        public static void main(String[] args) {
            try {
                final MyObject object = new MyObject();
                Thread thread = new Thread() {
                    @Override
                    public void run() {
                        object.setValue("a","aa");
                    }
                };
                thread.setName("a");
                thread.start();
                Thread.sleep(1000);
                Thread thread1 = new Thread() {
                    @Override
                    public void run() {
                        object.printUsernamePassword();
                    }
                };
                thread1.start();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    执行结果:

    源码地址:https://github.com/lilinzhiyu/threadLearning

    本文内容是书中内容兼具自己的个人看法所成。可能在个人看法上会有诸多问题(毕竟知识量有限,导致认知也有限),如果读者觉得有问题请大胆提出,我们可以相互交流、相互学习,欢迎你们的到来,心成意足,等待您的评价。

  • 相关阅读:
    Swift学习笔记(7)--控制流
    安装APK时报 Installation failed with message Failed to finalize session : INSTALL_FAILED_USER_RESTRICTED: Invalid apk.
    Android Notification 的四种使用方式
    Socket.io
    socket
    socket.io 中文手册 socket.io 中文文档
    Android中的CardView使用
    TabLayout实现底部导航栏(2)
    使用PagerSlidingTabStrip实现顶部导航栏
    TabLayout实现顶部导航栏(1)
  • 原文地址:https://www.cnblogs.com/lilinzhiyu/p/7986231.html
Copyright © 2011-2022 走看看