本节重点说说线程什么时候会阻塞,如何关闭

1 让出时间片

Thread.yield();
通知并建议线程调度器,我已经做完了主要工作,时间片你可以分给别人了
即使调用了这个,还是可能没有切换时间片,或者切换了,但是还是给了当前线程

Thread.sleep(1000);
TimeUnit.SECOND.sleep(1);
让当前线程进入睡眠状态,程序就阻塞在这里了
这个的表现应该是比yield良好多了

但这两个的特性,都不应该过于依赖
因为系统对时间片的划分是不可依赖的
你的程序也不应对时间片的划分有什么依赖

2 任务的自我检查

有些任务会在循环中检查状态值,如canceled之类的,会自己退出任务
但有时我们需要任务更突然的终止任务

注意:如果有标志位canceled,isRunning等,这个一般是volatile的

private volatile boolean isFinished = false;while(!isFinished){//do sth
}

如果不想用标志位,还可以检查是否被中断

while(!Thread.currentThread().isInterrupted()){//do sth
}

3 阻塞时终止

任务除了自我检查状态,也可能阻塞在sleep中,此时可能也需要将其终结

线程的状态:
——new:已经创建完毕,且已经start,资源分配完毕,等待分配时间片了,这个状态只会持续很短的时间,下一步就会进入运行或者阻塞
——run:就绪状态,只要给了时间片,就会运行,在任一时刻,thread可能运行也可能不运行
——block:阻塞状态,程序本身能够运行,但有个条件阻止了它运行,调度器会忽略这个线程,直到跳出阻塞条件,重新进入就绪状态
——dead:run()方法返回,或者被中断

都哪些方式可以进入block状态:
——sleep:等时间到
——wait:等notify
——等待IO,如stream.read()
——等待synchronized锁
——等待Lock锁

另外,如下的大循环也可以interrupt
while(!Thread.currentThread().isInterrupted()){ThreadLocalVariableHolder.increment();System.out.println(this);Thread.yield();
}

终结情形1:

//注意isCanceled是个boolean,而且一般会需要volatile修饰
public void run(){while(!isCanceled){//do some seriers work}
}

终结情形2:

//thread.interrupt()可以打断
//Executors得不到thread的引用,只能通过ExecutorService.shutdownNow()来打断
//如果能拿到Future,可以Future.cancel(true)来打断
//exec.execute(Runnable)看来是打断不了了,因为拿不到什么引用
//exec.submit(),还是能打断的,返回了Future
//本质上都是调用了thread.interrupt()关于shutdown:
shutdown():拒绝再接收新的task,但已有的task会执行到terminate
shutdownNow():禁止再接收新的task,已有task,在waiting的不会再start,已经执行的会尝试stop掉  未shutdown状态:线程池还在运行,不管有没有running,waiting的task,都会一直等待add新task(通过execute或者submit)
shutdown状态:执行完现有task,就会terminatepublic void run(){while(!Thread.currentThread().isInterrupt()){   //或者用Thread.interrupted()判断//do some seriers work}
}public void run(){while(true){Thread.sleep(1000); //被interrupt会抛出异常,因为既然是阻塞,被意外终止,异常看似挺合理//do some seriers work}
}

终结情形3:终结不了的synchronized

在等待synchronized的线程,不可以被interrupt
但是注意,Lock可以尝试获取锁,并可以指定阻塞等待锁的时间限制

终结情形4:ReentrantLock.lockInterruptly()

ReentrantLock.lockInterruptly(),在这里获取不到锁,会阻塞,但是可以被interrupt方法中断import java.util.concurrent.*;
import java.util.concurrent.locks.*;class BlockedMutex {private Lock lock = new ReentrantLock();public BlockedMutex() {// Acquire it right away, to demonstrate interruption// of a task blocked on a ReentrantLock:lock.lock();}public void f() {try {// This will never be available to a second tasklock.lockInterruptibly(); // Special callSystem.out.println("f()方法得到锁了??");} catch(InterruptedException e) {System.out.println("f()方法没得到锁,而是被中断了,被interrupt了");}}
}class Blocked2 implements Runnable {BlockedMutex blocked = new BlockedMutex();public void run() {System.out.println("等f()拿到ReentranLock");blocked.f();System.out.println("从f()返回了");}
}public class Interrupting2 {public static void main(String[] args) throws Exception {Thread t = new Thread(new Blocked2());t.start();TimeUnit.SECONDS.sleep(1);System.out.println("调用了t.interrupt()");t.interrupt();}
} /* Output:
Waiting for f() in BlockedMutex
Issuing t.interrupt()
Interrupted from lock acquisition in f()
Broken out of blocked call
*///:~

终结情形5:IO密集型阻塞

在等待InputStream.read()的线程,不可以被interrupt
但是有个笨办法:关闭线程正在等待的底层IO资源,如关闭Socket
还有个更好的选择:nio,提供了更人性化的中断,被阻塞的nio通道会自动响应中断

4 实例

无法被打断的例子

public static void main(String[] args) throws InterruptedException {Thread t = new Thread(new Runnable() {@Overridepublic void run() {while(true){System.out.println("go on...");}}});t.start();Thread.sleep(2000);t.interrupt();while(true){Thread.yield();}
}如果一个Runnable没有cancel类的标志位检查,也没有检查isInterrupt(),调用interrupt()会怎么地?
是关不掉的,但这种形式的无限循环,一般不会出现在真实场景里
真实场景什么样?一般是一个无限循环,但里面会阻塞(等待条件成熟),有跳出条件

处理InterrupttedException

线程被中断之后,会发异常InterrupttedException,有时需要清理资源,参考类c10.InterruptingIdiom


class NeedsCleanup {private final int id;public NeedsCleanup(int ident) {id = ident;System.out.println("NeedsCleanup " + id);}public void cleanup() {System.out.println("Cleaning up " + id);}
}class Blocked3 implements Runnable {private volatile double d = 0.0;public void run() {try {while(!Thread.interrupted()) {// point1NeedsCleanup n1 = new NeedsCleanup(1);// Start try-finally immediately after definition// of n1, to guarantee proper cleanup of n1:try {System.out.println("Sleeping");TimeUnit.SECONDS.sleep(1);// point2NeedsCleanup n2 = new NeedsCleanup(2);// Guarantee proper cleanup of n2:try {System.out.println("Calculating");// A time-consuming, non-blocking operation:for(int i = 1; i < 2500000; i++)d = d + (Math.PI + Math.E) / d;System.out.println("Finished time-consuming operation");} finally {n2.cleanup();}} finally {n1.cleanup();}}System.out.println("Exiting via while() test");} catch(InterruptedException e) {System.out.println("Exiting via InterruptedException");}}
}public class InterruptingIdiom {public static void main(String[] args) throws Exception {long delay = 2000;Thread t = new Thread(new Blocked3());t.start();TimeUnit.MILLISECONDS.sleep(delay);t.interrupt();}
} /* Output: (Sample)
NeedsCleanup 1
Sleeping
NeedsCleanup 2
Calculating
Finished time-consuming operation
Cleaning up 2
Cleaning up 1
NeedsCleanup 1
Sleeping
Cleaning up 1
Exiting via InterruptedException
*///:~

Java 6-2:收放自如,融汇贯通,让线程不再疯癫——线程的阻塞和关闭相关推荐

  1. 关于抽烟、戒烟、或者说是收放自如

    想抽烟的几种场景: 高兴的时候来一根 难过的时候来一根 焦虑的时候来一根 孤独的时候来一根 熬夜的时候来一根 饭后的时候来一根 聚会的时候来一根 看见别人抽自己也想来一根 习惯性的来一根(生物钟支配) ...

  2. 关于用d3.js画力导向图(Force-directed Graph)—如何让图收放自如

    使用d3画出很好看的力图,可以展示那种Neo4j知识图谱的效果.但是当一满屏都是小圆圈时又有点丧失了即看即懂的效果.因此需要实现对节点的收放. 主要是对生成力图的数据点集进行操作. 其中在收回某个节点 ...

  3. 收放自如的光剑-ShaderGraph

    前话 本期分享一个超酷的光剑效果.使用工具如下:ShaderGraph.PostProcess.UniRX(可选),可用脚本控制光剑的收放.先预览一下效果: 制作思路 Shader连线图如下 Posi ...

  4. 弹性伸缩Auto Scaling产品全面升级,轻松应对业务负载变化,张弛有度,收放自如!...

    弹性伸缩是阿里云上非常受欢迎的一个云服务编排产品,它能够根据用户的策略定义和业务需求变化,动态调整弹性计算资源,在有效支撑业务负载变化的同时保持最合理经济的基础设施费用开支.弹性伸缩可以根据用户设置的 ...

  5. 迟到的年度总结,我们应该收放自如

    现在已经2018年3月了,这篇2017的年度总结显得晚了一点,但意义非凡,让我有了更多的反省和思考,我相信大家读完一定会有收获.好了,废话不多说进入主题. 别用学习来逃避成长 这话说的简直是屁话,不是 ...

  6. 哈佛有只”精灵球“,唯有它能温柔收放深海的软体精灵 |Science Robotics

    几何栗 发自 凹非寺  量子位 出品 | 公众号 QbitAI △ "我的家,在海洋" 唯有温柔的精灵球,才能收住软体精灵.  这美如晶体的五角星,其实是一只温柔的机器人. 可 ...

  7. 物联无线自动窗帘:窗帘收放更自如-智能家居

    物联无线自动窗帘:窗帘收放更自如- 智能家居 大家都知道,窗帘是生活中最常见的一种设备,具有设计装饰.遮阳隔热.调节室内光线和营造舒适家居氛围的功能,同时也是保护家庭私密性一道"防火墙&qu ...

  8. matlab做比例积分微分控制,收放卷卷径计算+闭环摆杆控制参数自适应PID控制算法(变比例变积分变微分)介绍...

    项目简介 最近在一个客户现场搞熔边机项目,涉及到收放卷工艺的卷径计算,同时张力控制使用的是摆杆,然后通过PID控制输出辅助转速补偿收卷伺服速度.单一的PID参数不能自动适应卷径变化,如在小卷径200m ...

  9. 使用绞车和3PS滑轮计数器收放klein3000托鱼

    更多咨讯请见xiaok海洋测绘网 侧扫声纳klein3000在小渔船上作业时,因渔船上很少有绞车,托鱼的收放通过人力来实现. 这是需要将铠装缆按米做上标记,以便知道托鱼的layback(缆长). 如果 ...

最新文章

  1. atm java代码_用JAVA制作简单的ATM的代码 求教
  2. 从C语言的角度重构数据结构系列(八)-数据结构堆知识超级丑数
  3. 噪声强度(噪声功率) 噪声方差到底有什么关系?
  4. 笔记-中项案例题-2017年上-计算题
  5. (软件工程复习核心重点)第六章实现和测试-第五节:确认测试
  6. php 长整型转字符串 (convert long to string)
  7. post报文给mqtt服务器没有响应,post请求转为mqtt的方法
  8. android投屏到web,安卓投屏神器下载|安卓投屏神器(Web Video Caster)v4.5.4高级版下载 - 99安卓游戏...
  9. 组织人事领域信息化探索:开启编制、干部、人事一体化管理新模式
  10. C语言编程>第二十四周 ① 请补充fun函数,该函数的功能是判断一个数是否为素数。该数是素数时,函数返回字符串 “yes!”,否则函数返回字符串 “no!”,并在主函数中输出。
  11. 猿创征文 |【算法入门必刷】数据结构-栈(四)
  12. 如何修改win7上的mac地址
  13. 实战详解Maven部署(deploy)jar到私有仓库Nexus及如何引入私仓jar包
  14. 校园寝室管理系统-“轻舟校园”助力校园实现信息化、智能化管理
  15. 深度学习中一些时而会忘的概念
  16. 真人演示——怎样练腹肌最快最有效听语音
  17. java毕业设计电子书店管理系统Mybatis+系统+数据库+调试部署
  18. BUI前端框架·首页代码
  19. Web Security 之 Insecure deserialization
  20. 教你破解电脑五种开机密码方法

热门文章

  1. 因为在此系统上禁止运行脚本_按键精灵调试脚本常见问题
  2. AIRSKIN机器人电子皮肤
  3. 台式计算机怎样能搜无线连接,台式机怎么连接wifi,教您连接方法
  4. Mac 电脑下载 AppStore 中的 ipa 软件包详细流程
  5. MySQL- cluster集群----实现高可用
  6. 制作的excel表格如何放到微信公众平台文章中?
  7. 2021年度科技行业有哪些大事件?“杰出科技奖”公布36家企业领先科技技术
  8. pb开发的程序win10 报 sql server request resulted in a bad return code or status 的解决办法
  9. Games101课程笔记_lecture20_color颜色
  10. 如何在Office 2013或2016中带回Microsoft Office Picture Manager