zoukankan      html  css  js  c++  java
  • Java多线程程序休眠、暂停与停止

    休眠

      在Java多线程中,可以使用sleep()方法在指定毫秒数内让当前正在执行的线程休眠。
      下面这段代码,使得主函数的main线程休眠了2000ms,最后输出的间隔时间也是2000ms。

    public class MyThread extends Thread {
        public static void main(String[] args) {
            try {
                long begin;
                long end;
                begin = System.currentTimeMillis();
                System.out.println("begin = " + begin);
                Thread.sleep(2000);
                end = System.currentTimeMillis();
                System.out.println("end = " + end);
                System.out.println("end - begin = " + (end - begin) + "ms");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    

    输出结果:

    begin = 1486711105366
    end = 1486711107366
    end - begin = 2000ms

    暂停

      虽然suspend和resume方法可以分别使得线程暂停和回复,但是这两个方法因为有缺点而已经被弃用。

    缺点:

    • 独占:在使用suspend和resume方法时,如果使用不当,极易造成公共的同步对象独占,使得其他线程无法访问公共同步对象。
    • 不同步:在使用suspend与resume方法时也容易因为线程而导致数据不同步的情况。

    yield方法

      可以使用yield方法进行暂停。
      yield()方法的作用是放弃当前的CPU资源,将它让给其他任务去占用CPU执行时间。但放弃的时间不确定,有可能刚刚放弃,马上又获得CPU时间片。

    public class MyThread extends Thread {
        @Override
        public void run() {
            long beginTime = System.currentTimeMillis();
            int count = 0;
            for (int i = 0; i < 50000000; i++) {
                //Thread.yield();
                count = count + (i + 1);
            }
            long endTime = System.currentTimeMillis();
            System.out.println("用时: " + (endTime - beginTime) + "ms");
        }
    
        public static void main(String[] args) {
            MyThread myThread = new MyThread();
            myThread.start();
        }
    }
    

    输出结果:

    用时: 21ms

      去掉注释//Thread.yield()后。

    输出结果:

    用时: 4471ms

      从第二次输出可以看出,用时明显变长。

    停止

      虽然stop()可以停止一个线程,但是这个方法是不安全的,而且是已经被弃用作废的,最好不要使用它。

    interrupt()方法

      interrupt()方法的使用效果并不像for+break语句那个,马上就停止循环。调用interrupt()方法仅仅是在当前线程中打了一个停止的标记,并不是真正停止线程。

    判断线程是否是停止状态

    • this.interrupted():测试当前线程是否已经是中断状态,执行后具有将状态标志清楚为false的功能,为static方法。
    • this.isInterrupted():测试线程Thread对象是否已经是中断状态,但是不清除状态标志。
    public class MyThread extends Thread {
        public static void main(String[] args) {
            Thread.currentThread().interrupt();
            System.out.println("是否停止1? " + Thread.interrupted());
            System.out.println("是否停止2? " + Thread.interrupted());
            System.out.println("end");
        }
    }
    

    输出结果:

    是否停止1? true
    是否停止2? false
    end

    public class MyThread extends Thread {
        @Override
        public void run() {
            for (int i = 0; i < 50000; i++) {
                System.out.println(i);
            }
        }
    
        public static void main(String[] args) {
            try {
                MyThread myThread = new MyThread();
                myThread.start();
                Thread.sleep(1000);
                myThread.interrupt();
                System.out.println("是否停止1? " + myThread.isInterrupted());
                System.out.println("是否停止2? " + myThread.isInterrupted());
                System.out.println("end");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    

    输出结果(末尾):

    49997
    49998
    49999
    是否停止1? false
    是否停止2? false
    end

    能停止线程的方法

      在run中加一个判断,如果停止了,则break跳出循环体。

    public class MyThread extends Thread {
        @Override
        public void run() {
            for (int i = 0; i < 50000000; i++) {
                if (this.interrupted()) {
                    System.out.println("已经是停止状态了,我要退出了");
                    break;
                }
                System.out.println(i);
            }
        }
    
        public static void main(String[] args) {
            try {
                MyThread myThread = new MyThread();
                myThread.start();
                Thread.sleep(1000);
                myThread.interrupt();
                System.out.println("end");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    

    输出结果(末尾):

    160560
    160561
    160562
    160563
    160564
    end
    已经是停止状态了,我要退出了

      上述代码虽然可以停止线程,但是如果for的后面还有语句,那么还是会继续执行。
      因此可以用下述方法来解决。

    public class MyThread extends Thread {
        @Override
        public void run() {
            try {
                for (int i = 0; i < 50000000; i++) {
                    if (this.interrupted()) {
                        System.out.println("已经是停止状态了,我要退出了");
                        throw new InterruptedException();
                    }
                    System.out.println(i);
                }
                System.out.println("for结束");
            } catch (InterruptedException e) {
                System.out.println("进入run中的catch了");
                e.printStackTrace();
            }
    
        }
    
        public static void main(String[] args) {
            try {
                MyThread myThread = new MyThread();
                myThread.start();
                Thread.sleep(1000);
                myThread.interrupt();
                System.out.println("end");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    

    输出结果(末尾):

    152891
    152892
    152893
    152894
    end
    已经是停止状态了,我要退出了
    进入run中的catch了
    java.lang.InterruptedException
    at mythread.MyThread.run(MyThread.java:13)

  • 相关阅读:
    2
    1
    Java面试题整理二(侧重SSH框架)
    solr添加多个core
    Oracle SQL性能优化
    jQuery的$.ajax
    spring四种依赖注入方式
    通过JAXB完成Java对象与XML之间的转换
    window环境下将solr6.3部署到tomcat中
    Java面试题整理一(侧重多线程并发)
  • 原文地址:https://www.cnblogs.com/liuyang0/p/6386850.html
Copyright © 2011-2022 走看看