并发系列之「初探sleep()函数」

news/2024/7/3 7:17:12 标签: 多线程, java, thread, 并发编程

Thread 类中有一个静态的sleep方法,当一个执行中的线程调用了Thread的sleep方法后,调用sleep的线程会暂时让出指定时间的执行权,也就是在这期间不参与CPU的调度,但是该线程所拥有的监视器资源,比如还是持有不让出的。

指定的睡眠时间到了后该函数会正常返回,线程就处于就绪状态,然后参与CPU的调度,获取到CPU资源后就可以继续运行了。

如果在睡眠期间其他线程调用了该线程的interrupt()方法中断了该线程,则该线程会在调用sleep方法的地方抛出InterruptedException异常而返回。

下面举一个例子来说明,线程在睡眠时拥有的监视器资源不会被释放:

java">/**
 * @Author Hory
 * @Date 2020/10/19
 */
public class SleepTest {

    private static final Lock lock = new ReentrantLock();

    public static void main(String[] args) throws InterruptedException {
        Thread threadA = new Thread(new Runnable(){
            public void run(){
                lock.lock(); // 获取独占锁
                try{
                    System.out.println("child threadA is in sleep");
                    Thread.sleep(2000);
                    System.out.println("child threadA is awaked");
                }catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    lock.unlock(); // 释放锁
                }
            }
        });

        Thread threadB = new Thread(new Runnable(){
            public void run(){
                lock.lock(); // 获取独占锁
                try{
                    System.out.println("child threadB is in sleep");
                    Thread.sleep(2000);
                    System.out.println("child threadB is awaked");
                }catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    lock.unlock(); // 释放锁
                }
            }
        });

        // 启动线程
        threadA.start();
        threadB.start();
    }
}

运行结果:

java">child threadA is in sleep
child threadA is awaked
child threadB is in sleep
child threadB is awaked

如上代码首先创建了一个独占锁,然后创建了两个线程,每个线程在内部先获取锁,然后睡眠,睡眠结束后会释放锁。无论执行多少遍上面的代码都是线程A先输出或者线程B先输出,不会出现线程A和线程B交叉输出的情况。

从执行结果来看,这里线程A先获取了锁,那么线程A会先输出一行,然后调用sleep方法让自己睡眠2s,在线程A睡眠的这2s内那个独占锁lock还是线程A自己持有,线程B会一直阻塞直到线程A醒来后执行unlock释放锁。

下面再来看一下,当一个线程处于睡眠状态时,如果另外一个线程中断了它,会不会在调用sleep方法处抛出异常:

java">/**
 * @Author Hory
 * @Date 2020/10/19
 */
public class SleepTest1 {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new Runnable(){
            public void run(){
                try{
                    System.out.println("child thread is in sleep");
                    Thread.sleep(10000);
                    System.out.println("child thread is awaked");
                }catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {

                }
            }
        });

        thread.start();
        Thread.sleep(2000); // 主线程睡眠2秒
        thread.interrupt(); // 在主线程内调用子线程的interrupt()终端子线程
    }
}

运行结果:

java">child thread is in sleep
java.lang.InterruptedException: sleep interrupted
	at java.lang.Thread.sleep(Native Method)
	at testThread.SleepTest1$1.run(SleepTest1.java:13)
	at java.lang.Thread.run(Thread.java:748)

如上所示,主线程睡眠2秒,让子线程先运行,子线程在睡眠期间,主线程中断了它,所以子线程在调用sleep方法处抛出了InterruptedException异常。另外需要注意的是,如果在调用Thread.sleep(long millis)时为millis参数传递了一个负数,则会抛出IllegalArgumentException异常,如下所示:

java">Exception in thread "main" java.lang.IllegalArgumentException: timeout value is negative
	at java.lang.Thread.sleep(Native Method)
	at testThread.SleepTest1.main(SleepTest1.java:24)


http://www.niftyadmin.cn/n/1690235.html

相关文章

并发系列之「通过生产者消费者场景理解wait()/ notify() / notifyAll()」

wait(long timeout)/notify()/notifyAll() 网上好多解释不是不全面就是有偏差,还是直接看官方解释 先来看一下源码: public class Object {public final native void notify();public final native void notifyAll();public final native void wait(lo…

动态规划系列之「最大子序和」

53. 最大子序和 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 这道题不能用滑动窗口来做,因为数组中含有复数,这样就无法决定窗口的大小。 和为S的连续…

Spring 框架之「初识AOP 面向切面编程」

AOP简介 在软件行业,AOP为Aspect Oriented Programming 的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理 功能的统一维护的一种技术。 AOP是OOP(面向对象编程)的延续,是软件开发中的一个热点,也…

LeetCode系列之「回文子串」

647. 回文子串 给定一个字符串,返回这个字符串中有多少个回文子串。 两个相同的回文子串出现在不同的位置,认为是2个回文串。 a、aa、aaa、aba、aabaa、abcba均认为是回文子串。 示例1: 输入 "aaa"输出 6说明 a、a、a、aa、aa、…

动态规划系列之「编辑距离」

72. 编辑距离 给你两个单词 word1 和 word2,请你计算出将 word1 转换成 word2 所使用的最少操作数 。 你可以对一个单词进行如下三种操作: 插入一个字符删除一个字符替换一个字符 示例 1: 输入:word1 "horse", word2 …

从造轮子开始彻底理解LRU缓存机制

Leetcode146. LRU缓存机制 造轮子 在面试中,面试官一般会期望读者能够自己实现一个简单的双向链表,而不是使用语言自带的、封装好的数据结构。所以,造轮子还是很有必要的。 LRU 缓存淘汰算法就是一种常用策略。LRU 的全称是 Least Recentl…

机器学习笔记 - 基于深度学习和位置敏感哈希技术的近似重复的图像搜索

1、简述 接近实时获取相似图像是图像检索系统的重要用例 。在这里,我们使用局部敏感哈希 (LSH) 和顶部的随机投影构建类似的图像搜索实用程序,由预训练图像分类器计算的图像表示。 这种搜索引擎也是众所周知的 作为近似重复(或近重复)图像检测器。 我们还将研究优化在GPU…

LetCode系列之「用栈实现队列」

232. 用栈实现队列 请你仅使用两个栈实现先入先出队列。队列应当支持一般队列的支持的所有操作(push、pop、peek、empty) 直接上最优解 两个栈分别充当不同的角色: 一个只负责存(push)一个只负责取(pop) 假设负责存和取的栈分别为s1和s2&a…