java 线程中断机制
上一篇文章我们了解过了java有关线程的基本概念,有线程的属性,线程可能处于的状态,还有线程的两种创建的方式,最后还说了一个关键字synchronized,解决了高并发导致数据内容不一致问题,本篇文章就介绍线程的中断机制。
首先我们需要知道,java中的每个对象都是有内部对象锁的,其实每个java对象不止包含一个内部对象锁,还包含了一个等待队列和一个条件队列。
public synchronized void showName(){
************
}
这样的一个被synchronized关键字修饰的方法,如果已经有线程获得了该对象的锁,再有线程过来就会被阻塞并丢入等待队列中。
private int count;
public synchronized void showName(){
if(count==0){
wait();
}
}
public synchronized void setName(){
if(count==0){
notifyAll();
}
}
而在上述的代码段中,出现了两个方法:wait和notifyAll。这两个方法是成对出现的,wait主要作用是将当前线程阻塞并且置入条件队列上,notifyAll主要用于解放条件队列上的所有线程,使他们可以再次竞争处理机的调度以便运行。
小结一下,以上就比较了等待队列和条件队列的作用和区别。等待队列往往是因为想要申请的锁已经被别的线程占有了,需要置入等待队列等待占有锁的线程释放锁,然后接受处理机调度,被选中后方能获得锁并运行。而条件队列却是一个已经获得锁的线程在执行过程中发现自己继续运行的条件不满足(无法获得某些需要的资源),程序无法继续执行下去了,于是调用wait方法阻塞自己并释放外部对象锁,置入条件队列。
一旦占有某类资源的线程释放该资源之后,调用notifyAll方法释放所有在条件队列上等待的线程,使他们重新接受处理机的挑选。如果被处理机选中运行,就会从条件队列出队,占有对象锁,开始运行。需要注意的是:wait和notifyAll方法只能在synchronized修饰的代码块中调用,否则就会抛出异常。其实原因也很简单,wait必须指定将当前的线程挂在什么对象的条件队列上,notifAll必须被指定释放什么对象上的所有条件队列中的线程。synchronized关键字是针对某个对象加锁的,在其代码块中调用上述两种方法就默认操作被锁住的对象的条件队列。
一、如何中断
接下来我们看看线程的中断,有人会问:每个线程执行自己的程序,直到程序的最后一条代码,执行完成之后就会自动的死亡,为什么要使用中断机制来主动的让他死亡呢?其实在我们的程序中往往需要在程序执行的过程中显式的就是线程的运行。比如:有些线程永远不会执行结束,比如你打开浏览器访问网站,如果没有中断线程机制,你永远都不会等到线程运行结束的那一刻。只能通过显式的中断来结束一个线程的运行。
Thread类中定义了如下几个关于中断的方法:
public boolean isInterrupted()
public void interrupt()
public static boolean interrupted()
三者方法名类似,但是却具有完全不同的操作。isInterrupted() 方法其实就是判断当前线程是否被中断,interrupt() 方法表示将线程的中断状态置为true,interrupted() 方法是一个静态的方法,测试当前线程的中断状态是否为true,和第一种方法功能一样,但是这个方法有一个额外的操作:会将调用此方法的线程的中断状态位置为false。就是顺便将中断位置为false。
二、线程的不同的状态对中断的反应
我们知道线程的状态主要有,New,Runnable,Blocked,waiting,Terminated。下面我们看看每种状态下的线程对于中断的应对是怎么样的。
首先是New状态,New状态下的线程并没有处于运行状态,这个状态下,中断操作对该线程没有任何影响。中断标志位也不会被置为true。其实可以理解的,一个都没有机会运行的线程,本来就是处于类似于中断的状态下。这种状态和Terminated状态下的线程对于中断的反应是一样的。
下面我们看看Runnable状态下的线程是怎样的反应。一个正在运行的线程,如果调用了interrupt方法,只会将此线程的中断表示为置为true,一旦该线程在某个阶段检测自己的中断表示位,发现如果是true就会中断线程。但是在没有自我检测的期间,线程是可以正常运行的。
public class Test_thread extends Thread{
public void run(){
while(true) {
}
}
}
public class Test_Class {
public static void main(String[] args){
Thread thread = new Test_thread();
thread.start();
thread.interrupt();
try{
Thread.sleep(1000);
} catch (InterruptedException e){
};
System.out.println(thread.isInterrupted());
}
}
/*输出:true*/
如上述的程序运行结果所示,一个将正在运行的线程interrupt,虽然标示位已经被更改,但是线程不会因此被中断。
接下来看看Blocked状态下线程应对中断的反应。本篇文章的开头已经说过了,Bloked状态是由于申请某个对象的锁失败之后被放置在了该对象的等待队列上,这个队列上的线程都是Blocked状态的。在这种状态下,调用interrupt() 方法,一样的只会将该线程的中断标志位置为true但是不会导致该线程退出等待队列。
public class Test_Class {
private static Object count = new Object();
public static void main(String[] args){
try {
show();
}catch (InterruptedException e){}
}
public static void show() throws InterruptedException{
synchronized (count){
Thread thread = new myThread();
thread.start();
thread.interrupt();
System.out.println(thread.isInterrupted());
System.out.println(thread.getState());
thread.join();
}
}
public static class myThread extends Thread{
public void run(){
synchronized (count){
while(!Thread.currentThread().isInterrupted()){
}
System.out.println(this.toString());
}
}
}
}
/*
输出结果:
true
BLOCKED
*/
我们在main函数中调用show方法(这是一个线程),获取count的锁,在show方法内部创建一个线程,start之后执行run方法时没有能够获得count的锁,接着中断该线程,于是被阻塞在等待队列中。从输出的结果可以看出,一个状态是Blocked的线程在被中断之后,除了中断状态位被修改之后,其余没有什么变化。
最后,我们看线程的waiting状态,一个处于waiting状态的线程,执行方法interrupt,会导致抛出Inerruption异常,即不允许一个处于waiting状态的线程被中断。但是,有一点是:此异常被抛出之后,会清空中断标志位。
public class Test_thread extends Thread{
public void run(){
try {
Thread.sleep(1000);
}catch (InterruptedException e){
System.out.println(0);
}
}
}
public class Test_Class {
public static void main(String[] args){
Thread thread = new Test_thread();
thread.start();
try{
Thread.sleep(100);
}catch (InterruptedException e){
System.out.println(1);
}
thread.interrupt();
try {
thread.join();
}catch(InterruptedException e){
System.out.println(3);
}
}
}
启动新线程,调用sleep方法使该线程处于waiting状态,与此同时,主线程调用子线程的interrupt方法,中断该线程,于是处于waiting状态的线程抛出异常,被捕获之后输出0;
本篇文章结束,大家需要知道的就是在线程处于不同的状态下,遇到中断的处理方式是不一样的,对于是否就行处理其实还是取决与我们程序员写的代码。文章依然是自己阅读别人博客和自己总结实践得来,如果有错误,望大家指出来。感谢!
java 线程中断机制的更多相关文章
- Java线程中断机制-如何中断线程
介绍: 对于线程一共分为五个状态:新建状态,就绪状态,阻塞状态,运行状态,死亡状态,有时候把阻塞状态又分为同步阻塞和等待阻塞. 有时想让主线程启动的一个子线程结束运行,我们就需要让这个子线程中断,不再 ...
- Java基础知识强化16:深入分析Java线程中断机制
1.Thread.interrupt真的能中断线程吗? 在平时的开发过程中,相信都会使用到多线程,在使用多线程时,大家也会遇到各种各样的问题,今天我们就来说说一个多线程的问题——线程中断. ...
- Java 线程的中断机制
今天我们聊聊 Java 线程的中断机制. 线程中断机制提供了一种方法,用于将线程从阻塞等待中唤醒,并作出相应的“受控中断”处理. synchronized (lock) { try { while ( ...
- 【转载】 Java线程面试题 Top 50
Java线程面试题 Top 50 不管你是新程序员还是老手,你一定在面试中遇到过有关线程的问题.Java语言一个重要的特点就是内置了对并发的支持,让Java大受企业和程序员 的欢迎.大多数待遇丰厚的J ...
- Java线程面试题 Top 50 (转载)
转载自:http://www.cnblogs.com/dolphin0520/p/3958019.html 原文链接:http://www.importnew.com/12773.html 本文由 ...
- 50 道 Java 线程面试题(转载自牛客网)
下面是 Java 线程相关的热门面试题,你可以用它来好好准备面试. 1) 什么是线程? 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位.程序员可以通过它进行多处理 ...
- Java线程面试题 Top 50
转自:http://www.importnew.com/12773.html 不管你是新程序员还是老手,你一定在面试中遇到过有关线程的问题.Java语言一个重要的特点就是内置了对并发的支持,让Java ...
- java线程中断和终止线程运行
ava中启动一个线程很容易,通常情况下我们都是等到任务运行结束后让线程自行停止.但有时需要在任务正在运行时取消他们,使得线程快速结束.对此Java并没有提供任何机制.但是我们可以通过Java提供的线程 ...
- 【多线程】Java线程面试题 Top 50(转载)
Java线程面试题 Top 50 原文链接:http://www.importnew.com/12773.html 本文由 ImportNew - 李 广 翻译自 javarevisited.欢迎 ...
随机推荐
- 几种常用的控件(下拉框 可选框 起止日期 在HTML页面直接读取当前时间)
下拉框 <div class="form-group"> <label class="col-xs-3 c ...
- iOS 登陆之界面设置
1.界面构成 1.1. 效果图 1.2. 元素 背景图 用户名的输入框 密码的输入框 登陆按钮 忘记密码 用户注册 第三方登陆 两个分割线
- iOS开发之内存缓存机制
使用缓存的目的是为了使用的应用程序能更快速的响应用户输入,是程序高效的运行.有时候我们需要将远程web服务器获取的数据缓存起来,减少对同一个url多次请求. 内存缓存我们可以使用sdk中的NSURLC ...
- InnoDB的表类型,逻辑存储结构,物理存储结构
表类型 对比Oracle支持的各种表类型,InnoDB存储引擎表更像是Oracle中的索引组织表(index organized table).在InnoDB存储引擎表中,每张表都有个主键,如果在创建 ...
- jquery $.getJSON()跨域请求
以前总是没搞明白是怎么回事,现在是迫不得已,就仔细看了看说明文档,终于测试成功了,记下 1,同一域名下和其他的请求可以是一样的 js: 代码如下: var url="http://loc ...
- Update关联查询不走索引,效率低下
优化一个sql,就是有A,B两个表,要利用b表的字段更新a表对应的字段.形如 Sql代码 update A set A.a=(select B.b from B where A.id=B.id); 原 ...
- JAVA轻量级文件监控
原文地址:http://blog.csdn.net/three_man/article/details/31012903?utm_source=tuicool 介绍 本文主要介绍一种轻量级的文件监控方 ...
- Swiper.js使用遇到的问题总结onSlideChangeEnd回调偶尔触发,偶尔不触发等;
Swiper 是一个开源免费的移动触摸插件. 在使用中遇到这样一个问题,记录一下. page 间切换效果 使用 fade 的时候,如果每个页面的大小不一样, 比如第一个页面全屏, 第二个页面比第一个小 ...
- Mockito教程
Mockito教程 2017-01-20 目录 1 Mockito 介绍 1.1 Mockito是什么? 1.2 为什么需要Mock 1.3 Stub和Mock异同 1.4 Mockito资 ...
- MongoDB基础之七 用户管理
MongoDB的用户管理 注意:A)在mongodb中,有一个admin数据库, 牵涉到服务器配置层面的操作,需要先切换到admin数据.即 use admin , -->相当于进入超级用户管理 ...