[TOC]
## 1. sleep
1. wait,sleep,join,I/O导致的block,会被interrupted方法中断.
2. 这些可中断方法,在捕捉到中断信号后,也就是捕获了InterruptedException异常,就会擦出interrupt标识。
![](https://img.kancloud.cn/5e/25/5e25031c64ea05891284fe4d5cf47d50_1018x262.png)
因为捕获到了信号,所以标识被擦出,输出false
## 1.1 特性
1、使线程进入执行时间的休眠
2、不会放弃monitor锁的所有权
## 1.2 TimeUnit
### 1.2.1 省去换算,表达清晰
是一个枚举类,对sleep进行了很好的封装,并省去了时间换算的过程。例如使线程休眠4分15秒
1、以前的写法是
~~~
Thread.sleep(4*60*1000 + 15 * 1000);
~~~
2、TimeUnit省去换算 ,而且清晰
~~~
TimeUnit.MINUTES.sleep(4);
TimeUnit.SECONDS.sleep(15);
~~~
### 1.2.2 时间不同单位之间的换算
TimeUnit还提供了便捷方法用于把时间转换成不同单位,例如,如果你想把秒转换成毫秒,你可以使用下面代码:
~~~
TimeUnit.SECONDS.toMillis(129)
~~~
TimeUnit更加强大,在需要使用sleep的时候,建议使用TimeUnit
## 2. yield
### 2.1 特性
yield属于一种启发式的方法,会提箱调度器表示当前线程原因放弃cpu资源,如果cpu资源不紧张,则会忽略这种题型。
## 3. yield于sleep
1、sleep只是暂时停止,没有时间片的消耗
2、yield执行后,如果调度器没有忽略这个提示,则会导致上下文切换。
3、sleep可以捕捉到interrupt信号,yield不能
### 3.1 wait和sleep的区别
一、wait特性:
1. 线程调用了某个对象的wait方法后,都会放入该对象monitor相关联的wait set 中,并释放monitor的所有权!
2. notify唤醒wait set中的一个thread,notifyall唤醒wait set中所有的阻塞线程,唤醒后仍需要争夺锁
二、wait和sleep的区别
1、wait是Object类的方法,所有类都有这个方法,sleep是Thread特有的方法
2、wait必须持有对象的monitor锁,也是就说wait必须在同步方法中执行
3、wait会释放锁,sleep不会释放锁
4、wait需要在同步方法中执行,sleep不需要。而且要求执行wait的方法和同步所用的锁关联对象是同一个。
![](https://img.kancloud.cn/d3/f4/d3f41fb67920a455a156491bc08bf93d_635x302.png)
同步对象是this,但是调用MUTEX的wait方法,此时会抛出IllegalMonitorStateException!
### 3.2 wait和sleep的相同点
1、sleep和wait都是可中断方法,被打断后,都会收到中断异常InterruptdException,同时擦除interrupt标识
## 4. interrupt
### 4.1 interrupt特性
1、只对由于wait,sleep,join等造成阻塞的线程起作用!对于没有阻塞的线程 不起作用
2、interrupt和stop不同的是,它不会终止整个线程,而是终止Object.wait, Thread.join和Thread.sleep三种方法造成的阻塞状态,果在调用它时,线程处于阻塞状态了,调用interrupt会抛出InterruptedException
3、打断一个线程并不是线程的生命周期的结束,而是打断了线程的阻塞状态
~~~
package com.tuna.test.thread;
public class InterruptThread1 extends Thread {
public static void main(String[] args) {
InterruptThread1 t = new InterruptThread1();
t.start();
try {
Thread.sleep(1000);
t.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void run() {
for (int i = 0; i <= 200000; i++) {
try {
Thread.sleep(2000);
System.out.println("i=" + i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
~~~
如下输出,中断异常后,不会影响线程的继续执行
```
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at com.tuna.test.thread.InterruptThread1.run(InterruptThread1.java:21)
i=1
i=2
i=3
i=4
i=5
...
```
**执行interrupted方法和可中断方法拦截InterruptedException后会擦出中断标记**
### 4.2 实例
![](https://img.kancloud.cn/8e/4b/8e4ba2c36c0e46bea7cbd2d862f529d9_1160x676.png)
两毫秒后,主线程打断子线程的阻塞,子线程捕获中断异常,输出“Oh,i am be interrupted”
### 4.3 interrupt flag
1、每个线程都有一个interrupt flag,当调用线程被interrupt,该标记会被设置
2、当线程调用了可中断方法进入阻塞时,调用interrupt方法被调用,flag将会被清除,说明线程已经打断了interrupt状态(非阻塞),此时调用isInterrupted方法时,返回false。
### 4.4 判断线程是否被中断
1、**isInterrupted**
判断线程是否被中断
![](https://img.kancloud.cn/6a/9e/6a9e8df6605fea08491c68ba0e6489df_1253x631.png)
![](https://img.kancloud.cn/23/6e/236ed52fd94ee9db62efe3d13eaf9a99_611x116.png)
**调用sleep可中断方法,进入阻塞**
第一次输出,因为没有被中断,所以输出false
第二、三输出时,线程被中断,但是**interrupt flag被擦除了**,依然输出false
2、 **interrupted**
判断是否被中断
1)如果线程被打断了,第一次调用interrupted将返回true,并立即擦除interrupt flag标记
2)第二次及以后调用interrupted都会返回false,除非次线程再一次被打断
![](https://img.kancloud.cn/f3/2f/f32fd7dce0cb726e46b7b206e36ce20c_1050x567.png)
子线程不断输出,期间main线程打断了一下子线程,所以会输出一次true,并且马上擦擦除标记,继续输出 false。
由此看出,**interrupt不会影响非阻塞(可中断)的线程的继续执行**
## 5. join
阻塞线程,可中断
B调用A线程join方法,b进入阻塞,知道A执行完成
## 6 线程进入runnable状态
1、阻塞I/O完成,比如网络i/o完成,进入runnable状态
2、完成了指定得休眠sleep,进入runnable状态
3、wait中的线程被其他线程notify/notifyall唤醒,进入runnable状态
4、获取到了某个锁资源,进入runnable状态
5、线程在阻塞过程中,被其他线程interrupted,进入runnable状态
- 计算机网络
- 基础_01
- tcp/ip
- http转https
- Let's Encrypt免费ssl证书(基于haproxy负载)
- what's the http?
- 网关
- 网络IO
- http
- 工具
- Git
- 初始本地仓库并上传
- git保存密码
- Gitflow
- maven
- 1.生命周期命令
- 聚合与继承
- 插件管理
- assembly
- 资源管理插件
- 依赖范围
- 分环境打包
- dependencyManagement
- 版本分类
- 找不到主类
- 无法加载主类
- 私服
- svn
- gradle
- 手动引入第三方jar包
- 打包exe文件
- Windows
- java
- 设计模式
- 七大原则
- 1.开闭原则
- 2. 里式替换原则
- 3. 依赖倒置原则
- 4. 单一职责原则
- 单例模式
- 工厂模式
- 简单工厂
- 工厂方法模式
- 抽象工厂模式
- 观察者模式
- 适配器模式
- 建造者模式
- 代理模式
- 适配器模式
- 命令模式
- json
- jackson
- poi
- excel
- easy-poi
- 规则
- 模板
- 合并单元格
- word
- 读取
- java基础
- 类路径与jar
- 访问控制权限
- 类加载
- 注解
- 异常处理
- String不可变
- 跨域
- transient关键字
- 二进制编码
- 泛型1
- 与或非
- final详解
- Java -jar
- 正则
- 读取jar
- map
- map计算
- hashcode计算原理
- 枚举
- 序列化
- URLClassLoader
- 环境变量和系统变量
- java高级
- java8
- 1.Lambda表达式和函数式接口
- 2.接口的默认方法和静态方法
- 3.方法引用
- 4.重复注解
- 5.类型推断
- 6.拓宽注解的应用场景
- java7-自动关闭资源机制
- 泛型
- stream
- 时区的正确理解
- StringJoiner字符串拼接
- 注解
- @RequestParam和@RequestBody的区别
- 多线程
- 概念
- 线程实现方法
- 守护线程
- 线程阻塞
- 笔试题
- 类加载
- FutureTask和Future
- 线程池
- 同步与异步
- 高效简洁的代码
- IO
- ThreadLocal
- IO
- NIO
- 图片操作
- KeyTool生成证书
- 压缩图片
- restful
- 分布式session
- app保持session
- ClassLoader.getResources 能搜索到的资源路径
- java开发规范
- jvm
- 高并发
- netty
- 多线程与多路复用
- 异步与事件驱动
- 五种IO模型
- copy on write
- code style
- 布隆过滤器
- 笔试
- 数据库
- mybatis
- mybatis与springboot整合配置
- pagehelper
- 分页数据重复问题
- Java与数据库之间映射
- 拦截器
- 拦截器应用
- jvm
- 堆内存测试
- 线程栈
- 直接内存
- 内存结构
- 内存模型
- 垃圾回收
- 调优
- 符号引用
- 运行参数
- 方法区
- 分带回收理论
- 快捷开发
- idea插件
- 注释模板
- git
- pull冲突
- push冲突
- Excel处理
- 图片处理
- 合并单元格
- easypoi
- 模板处理
- 响应式编程
- reactor
- reactor基础
- jingyan
- 规范
- 数据库