关于线程sleep的一个小问题

Posted 你是我世界的光

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于线程sleep的一个小问题相关的知识,希望对你有一定的参考价值。

之前在网上看过一篇博客。就该博客的程序的个人有疑惑的问题这里记录一下。

博客的程序是这样的:

import java.util.Date;

public class testSleep


    public static void main(String[] args)
    
        // 创建并启动线程
        MyThread thread = new MyThread();
        thread.start();
        try
        
            // 主线程沉睡10s
            Thread.sleep(10000);
         catch (Exception e)
        
            // TODO: handle exception
            e.printStackTrace();
        
        // 打断线程
        thread.interrupt();
    


class MyThread extends Thread


    @Override
    public void run()
    
        // TODO Auto-generated method stub
        while (true)
        
            // 打印系统时间
            System.out.println(new Date());
            try
            
                // 当前线程沉睡1S
                sleep(1000);
             catch (InterruptedException e)
             // 当被打断时,结束线程
                return;
            
        
    

下面是运行结果:

Sun Jul 24 22:45:48 CST 2016
Sun Jul 24 22:45:49 CST 2016
Sun Jul 24 22:45:50 CST 2016
Sun Jul 24 22:45:51 CST 2016
Sun Jul 24 22:45:52 CST 2016
Sun Jul 24 22:45:53 CST 2016
Sun Jul 24 22:45:54 CST 2016
Sun Jul 24 22:45:55 CST 2016
Sun Jul 24 22:45:56 CST 2016
Sun Jul 24 22:45:57 CST 2016

看上面的运行结果,在我看来这个运行结果是很有迷惑性。

这里简要说一下上述程序运行的过程:

启动程序,首先进入主线程,接着主线程启动了一个thread线程,然后主线程沉睡10秒,也就是说在这10秒内让出CPU,thread线程获得CPU,打印日期,沉睡1秒,再打印日期,再沉睡1秒,如此循环直至10秒钟之后主线程苏醒,然后主线程对thread线程进行中断,导致thread线程中断然后返回,程序结束。

下面我们对结果分析一下,我们看到,结果是打印了10个日期。其实,thread的沉睡和打印语句执行之间,他们的时间排列是串行的。也就是,执行完1秒的沉睡,然后就会执行打印语句。当然,打印语句也是要耗费时间的,这样看来似乎10秒内并不能打印10次,因为仅仅沉睡10次就会耗费10秒钟的时间,再加上10次打印的时间,总共就会超出10秒的时间。但是,由于打印语句耗时极短,注意,这里是极短(几万条打印语句才可能有秒级别的时间)。加之sleep语句的计时并不是很精确(sleep并不能用来进行精确的计时操作),因此会打印10次。

下面我们将上述程序改动一下,即将打印操作修改为一个十分耗时的打印操作,程序如下:

import java.util.Date;

public class testSleep


    public static void main(String[] args)
    
        // 创建并启动线程
        MyThread thread = new MyThread();
        thread.start();
        try
        
            // 主线程沉睡10s
            Thread.sleep(10000);
         catch (Exception e)
        
            // TODO: handle exception
            e.printStackTrace();
        
        // 打断线程
        thread.interrupt();
    


class MyThread extends Thread


    @Override
    public void run()
    
        // TODO Auto-generated method stub
        while (true)
        
            // 打印系统时间
            System.out.println(new Date());
            for (int a = 0; a < 100000; a++)
            
                for (int b = 0; b < 100000; b++)
                
                    for (int c = 0; c < 100000; c++);
                
            
            try
            
                // 当前线程沉睡1S
                sleep(1000);
             catch (InterruptedException e)
             // 当被打断时,结束线程
                return;
            
        
    

下面是运行结果:

Sun Jul 24 23:11:36 CST 2016
Sun Jul 24 23:11:41 CST 2016
Sun Jul 24 23:11:45 CST 2016

从上面的结果我们可以看出,当打印语句需要耗费较长时间的时候,运行结果不再打印10个,而是打印了3个。因此我们可以确定,主线程沉睡的10s内,thread线程打印耗费时间,然后睡一段时间,再打印耗费一段时间,再睡一段时间…

以上是关于关于线程sleep的一个小问题的主要内容,如果未能解决你的问题,请参考以下文章

Java多线程和Thread.sleep [重复]

C#中关于Thread.sleep(1000)的问题!!

关于线程的synchronized,wait,sleep,notify的一段有趣的代码

关于sleep的理解

关于线程的整理

java中的interrupt(),InterruptException和wait(),sleep()