关于线程sleep的一个小问题

本文讨论了线程sleep期间,另一个线程执行打印操作的时序问题。通过分析程序运行过程,揭示了线程执行、打印及sleep的交错行为。在原始程序中,尽管sleep了10秒,但由于打印耗时极短,总共打印了10次。当打印变为耗时操作,打印次数减少到3次,说明线程的执行受到CPU时间片分配的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

博客的程序是这样的:

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线程打印耗费时间,然后睡一段时间,再打印耗费一段时间,再睡一段时间…

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值