Java中的线程休眠大法系列(一)Thread.sleep() |
您所在的位置:网站首页 › sleep10是等待多久 › Java中的线程休眠大法系列(一)Thread.sleep() |
文章目录
前言Thread.sleep()1.看看JDK中此方法上面的注释2.案例展示(线程状态:TIMED_WAITING)3.案例展示(InterruptedException异常会清除interrupted status)4.案例展示(sleep不会释放monitors锁)
总结
前言
如果让一个线程进入休眠? 我们第一个想到的就是Thread.sleep(long millis)方法吧! 如果你对synchronized足够了解的话,那么你肯定还能想到Object.wait()方法。 再如果你对java的Lock锁足够了解的话,那么你还能想到LockSupport类的park()方法。 那么我们接下来就来对比分析一下这三种方式的使用场景和背后的区别,方便我们以后使用的时候,选择一个最合适的方式来处理我们的代码。 Thread.sleep() 1.看看JDK中此方法上面的注释Thread.sleep()方法必须有一个参数,此参数表示休眠的时长。 此方法会使得当前线程进入TIMED_WAITING状态,但是不会释放当前线程所持有的锁。 另外,此方法还会抛出一个InterruptedException的异常,这是受检查异常,调用者必须处理。而且当exception被抛出来的时候,这个“interrupted status”也会被清除。这句话怎么理解呢?等会我们举个例子看一下。 下面我看一下此方法上面的注释都说了什么内容: 代码如下(展示状态为:TIMED_WAITING): package com.kinyang; /** * @author KinYang.Lau * @date 2021/6/10 6:37 下午 */ public class ThreadSleepTest { public static void main(String[] args) throws InterruptedException { 创建一个 t1 线程 Thread t1 = new Thread(new Runnable() { @Override public void run() { try { System.out.println("t1 线程执行 sleep()方法... "); /// 线程 进入休眠 5s Thread.sleep(5000L); } catch (InterruptedException e) { e.printStackTrace(); } } },"t1-thread"); 启动t1线程 t1.start(); /// 这里让主线程休眠1s后,再查看 t1 线程的状态,确保t1线程已经执行 Thread.sleep(1000L); System.out.println("t1 线程当前状态:"+t1.getState()); } }输出结果我们看到,执行sleep之后,线程是TIMED_WAITING状态。 代码如下: package com.kinyang; /** * @author KinYang.Lau * @date 2021/6/10 6:37 下午 */ public class ThreadSleepTest { public static void main(String[] args) throws InterruptedException { 创建一个 t1 线程 Thread t1 = new Thread(new Runnable() { @Override public void run() { try { System.out.println("t1 线程执行 sleep()方法,休眠5s "); /// 线程 进入休眠 5s Thread.sleep(5000L); } catch (InterruptedException e) { System.out.println("捕获到 InterruptedException 异常!"); System.out.println("查看 t1.线程的 interrupted status :"+Thread.interrupted()); } } },"t1-thread"); 启动t1线程 t1.start(); /// 这里让主线程休眠1s后,再查看 t1 线程的状态,确保t1线程已经执行 Thread.sleep(100L); System.out.println("t1 线程当前状态:"+t1.getState()); System.out.println("此时执行:interrupt()方法 强制打断线程..."); t1.interrupt(); } }运行结果: 也就是说,sleep方法抛出的异常,会把线程的打断状态清除掉。 那么我们是怎么知道线程有这个状态呢?如果不调用sleep方法,我们打断线程,看看这个interrupt status会不是true? 我们再写个例子 public class ThreadSleepTest2 { public static void main(String[] args) throws InterruptedException { 创建一个 t1 线程 Thread t1 = new Thread(() -> { while (true){ if (Thread.interrupted()){ System.out.println("t1 线程被打断了!我们马上查看 Thread的 interrupted status :"+Thread.interrupted()); }else { System.out.println("t1 线程正常执行一项耗时操作,看电影...."); watchMV(); } } },"t1-thread"); 启动t1线程 t1.start(); /// 这里让主线程休眠1s后,再查看 t1 线程的状态,确保t1线程已经执行 Thread.sleep(1000L); System.out.println("t1 线程当前状态:"+t1.getState()); System.out.println("此时执行:interrupt()方法 强制打断线程..."); t1.interrupt(); } /** * 此方法,模拟一个耗时的操作 */ public static void watchMV(){ try { FileInputStream inputStream = new FileInputStream("/Users/xxxx.mp4/"); /// 这里将byte数组设置小一些,好让此方法执行慢点,可以看出效果 byte[] bytes = new byte[10]; // 读入多个字节到字节数组中,read为一次读入的字节数 while (inputStream.read(bytes) != -1) { } System.out.println("看完了!"); } catch (IOException e) { e.printStackTrace(); } } }运行结果 A thread interruption ignored because a thread was not alive * at the time of the interrupt will be reflected by this method * returning false. * * @return true if the current thread has been interrupted; * false otherwise. * @see #isInterrupted() * @revised 6.0 */ public static boolean interrupted() { return currentThread().isInterrupted(true); } 从这个案例我们可以看到,线程如果被interrupted的话,是会有状态变化的,证明了线程存在这个状态。 现在我们回过头来sleep方法注释上面写的下面这段话就能理解所谓的interrupted status是什么意思了。 if any thread has interrupted the current thread. The interrupted status of the current thread is cleared when this exception is thrown.`try catch sleep的方法后,执行Thread.interrupted()得到的结果永远都是false,因为catch后会清除了打断状态。 4.案例展示(sleep不会释放monitors锁) package com.kinyang.thread; import java.util.Scanner; /** * @author KinYang.Lau * @date 2021/6/10 6:37 下午 */ public class ThreadSleepTest3 { private static Object monitor = new Object(); public static void main(String[] args) throws InterruptedException { 创建一个 t1 线程 Thread t1 = new Thread(() -> { System.out.println("t1 尝试获取锁"); synchronized (monitor){ System.out.println("t1 获取到锁"); System.out.println("t1 执行 Thread.sleep() 方法,休眠该线程!"); /// 我们执行 sleep 操作,让线程进入休眠,看看其他线程是否能抢到 monitor 锁, /// 如果其他线程可以获取到 monitor 锁后,那么说明sleep会释放monitor锁 /// 否则,说明sleep不会释放monitor锁 try { Thread.sleep(5000L); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("t1 线程执行完成"); } },"t1-thread"); 启动t1线程 t1.start(); /// 这里让主线程休眠1s后,确保t1线程已经执行,并获取到锁 Thread.sleep(1000L); Thread t2 = new Thread(() -> { System.out.println("t2 尝试获取锁"); synchronized (monitor){ System.out.println("t2 获取到锁"); System.out.println("执行 t2 方法"); } },"t2-thread"); t2.start(); Scanner scanner = new Scanner(System.in); while (scanner.hasNextLine()) { if (scanner.nextLine().equalsIgnoreCase("bye")){ System.out.println("再见"); break; }else { System.out.println("指令错误"); } } } }执行结果 这一点以后我们会和Object.wait()方法做对比,做完对比后你就知道什么是释放锁,什么是不释放锁了。 总结简单总结一下,Thread的sleep方法的特性是: 1、必须指定休眠时长,休眠后线程转为TIMED_WAITING状态 2、sleep方法会抛出一个受检查异常InterruptedException,我们必须try catch处理。 3、sleep抛出异常后,会清除掉“线程打断状态”。所以在catch的代码块里,执行Thread.interrupted()得到的结果永远都是false 4、sleep不会丢掉monitors,也就是不会释放锁。 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |