`

Java Concurrent之 java线程中断

 
阅读更多

  中断(Interrupt):java中的每个线程自身都维护这一个boolean型的中断标识(JVM帮我们搞定了),唯有通过Thread.interrupt()方法可以将其置为true,(我们可以通过interrupted()/isInterrupted()方法来判断线程是否处于中断状态,需要注意的是:interrupted()方法会重置线程的中断状态,即将标识置为false),线程遇到中断,并不会立即停止,而且线程会是死亡、等待新的任务亦或是无视中断继续运行,这都还取决于程序本身的处理。

   其实,java也试图提供过抢占式中断,像已经被deprecated的Thread.stop()、Thread.suspend()、Thread.resume等,都问题多多。现在java的线程调度采用协作式中断,原理很简单:轮询某个表示中断的标记。

 

/**
 * @author Sonicery_D
 * @date 2014年12月23日
 * @version 1.0.0
 * @description
 **/
public class TestInterrupt implements Runnable{

	volatile boolean isInterrupted = false;
	@Override
	public void run() {
		while(true){
			if(isInterrupted){
				System.out.println("isInterrupted ............");
				break;
			}
			System.out.println("test---Interrupt---"+System.currentTimeMillis());
		}
	}

	
	public static void main(String[] args){
		TestInterrupt testInterrupt = new TestInterrupt();
		Thread t = new Thread(testInterrupt);
		t.start();
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("发起中断...");
		testInterrupt.isInterrupted = true;
	}
}

 但是当我们遇到阻塞方法时,上述的代码就束手无策了。如Object.wait()/Thread.sleep()/Thread.join()等阻塞方法

 

  注意通常我们调用Thread.interrupt()方法时无法立即引发中断的,它还是设置了JVM内部维护的中断标志,通过这个思路,应用程序可以检查中断标志来做一些特殊操作或者忽略掉中断。

 

/**
 * @author Sonicery_D
 * @date 2014年12月23日
 * @version 1.0.0
 * @description
 **/
public class TestInterrupt implements Runnable{

	volatile boolean isInterrupted = false;
	@Override
	public void run() {
		while(true){
			if(Thread.currentThread().isInterrupted()){
				System.out.println("isInterrupted ............");
				break;
			}
			System.out.println("test---Interrupt---"+System.currentTimeMillis());
		}
	}

	
	public static void main(String[] args){
		TestInterrupt testInterrupt = new TestInterrupt();
		Thread t = new Thread(testInterrupt);
		t.start();
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("发起中断...");
		t.interrupt();//调用Thread.interrupt()是无法立即引发中断 只是将JVM内部维护的中断标志置为true
//		testInterrupt.isInterrupted = true;
	}
}

  在执行线程调度的阻塞调用时(Object.wait()/Thread.sleep()/Thread.join())如果发生中断,被阻塞线程会“尽可能快的”抛出InterruptedException。因此我们可以对阻塞时的中断作出处理。

 

 

public class TestInterrupt implements Runnable{

	volatile boolean isInterrupted = false;
	@Override
	public void run() {
		while(!isInterrupted){
			try {
				Thread.sleep(5000);
				System.out.println("test---Interrupt---"+System.currentTimeMillis());
			} catch (InterruptedException e) {
				e.printStackTrace();
				System.out.println("occur the interrupted ... ...");
			}
		}
	}

	
	public static void main(String[] args){
		TestInterrupt testInterrupt = new TestInterrupt();
		Thread t = new Thread(testInterrupt);
		t.start();
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("发起中断...");
		testInterrupt.isInterrupted = true;
		t.interrupt();
	}
}

   我们也可以不使用volatile修饰的可见变量,使用Thread.interrupted()/Thread.isInterrupted()来判断是否需要中断

 

 

/**
 * @author Sonicery_D
 * @date 2014年12月23日
 * @version 1.0.0
 * @description
 **/
public class TestInterrupt implements Runnable{

	@Override
	public void run() {
		while(true){//Thread.interrupted() 会将中断状态重置为false
			try {
				test();
			} catch (InterruptedException e) {//注意这里因为上层再没有需要判断中断的方法,所以我并没有继续向上层方法调用栈抛异常 
				e.printStackTrace();
				System.out.println("occur the interrupted ... ...");
break;
			}
		}
	}

	public void test() throws InterruptedException{
		if(Thread.interrupted()){
			throw new InterruptedException("test 操作发生了中断 ... ...");
		}
	}
	public static void main(String[] args){
		TestInterrupt testInterrupt = new TestInterrupt();
		Thread t = new Thread(testInterrupt);
		t.start();
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("发起中断...");
		if(t.isAlive())
		t.interrupt();
	}
}

   在任务和线程分离的框架中,任务通常不能提前知道会被那个线程执行,也就不知道具体调用线程处理中断的策略,故 在任务被设置了中断标志后并不能保证任务会被取消。

 

  一般来说除非你知道线程的中断策略,否则我们不应该中断它。例如,我们不应直接调用Executor之类的框架线程的interrupt方法,应该调用类似Future.cancel方法来取消任务。

   另外,任务代码不应该猜测中断对执行线程的含义。一般代码遇到InterruptedException时,不应捕捉后将其“吃掉” 应该继续向上层 抛出。

分享到:
评论

相关推荐

    java concurrent 精简源码

    本资源“java concurrent 精简源码”着重关注Java并发库(java.util.concurrent)的核心概念,包括阻塞队列和线程管理。下面将详细阐述这些知识点。 1. **Java并发库(java.util.concurrent)** Java并发库是Java ...

    Java Concurrent Programming

    线程中断是一种控制线程运行状态的方式,可以通过调用`interrupt()`方法来中断线程。需要注意的是,中断操作并不立即停止线程,而是设置线程的中断标志。 ##### 2.4 阻塞方法 在多线程环境中,某些方法可能需要...

    面试-Java一些常见面试题+题解之多线程开发-JavaConcurrent.zip

    - Java线程具有优先级,但实际调度很大程度上依赖于操作系统,不保证优先级高的线程优先执行。 10. **中断机制** - Thread类的interrupt()方法用于请求中断线程,isInterrupted()和interrupted()检查中断状态。 ...

    JAVA-JavaThreadProgramming-Sams.zip_JAVA 设计_java 多线程_java 线程_多线程

    Java线程编程是Java开发中的重要组成部分,尤其在构建高性能、高并发的应用程序时不可或缺。本资料"JAVA-JavaThreadProgramming-Sams.zip"提供了一套详细的教程,旨在深入讲解Java中的多线程设计和实现。 Java多...

    java面试题之多线程.pdf

    9. **并发集合**:`java.util.concurrent`包提供线程安全的集合类,如`ConcurrentHashMap`, `CopyOnWriteArrayList`等,它们在多线程环境下提供了高效的数据访问。 总之,Java中的多线程涉及的内容广泛,包括线程的...

    Java线程超时监控

    首先,我们可以使用`java.util.concurrent`包中的`Future`和`ExecutorService`来实现线程超时。`ExecutorService`是一个接口,它提供了管理和控制线程池的能力,而`Future`则表示异步计算的结果。当我们提交一个任务...

    Java多线程编程核心技术_完整版_java_

    1. java.util.concurrent包下的工具类,如CountDownLatch、CyclicBarrier、Semaphore等,用于协调多个线程之间的操作。 以上内容只是《Java多线程编程核心技术》教程中的一部分核心知识点,实际学习中还需要结合...

    Java多线程编程线程的协同、停止、暂停、继续等操作实现

    `java.util.concurrent`包中的`ExecutorService`和`ThreadPoolExecutor`类提供了高级线程管理功能。线程池可以方便地管理和控制线程的创建、执行和销毁,包括停止所有线程的`shutdown()`和立即停止并取消所有任务的...

    JAVA线程学习(源代码)

    Java线程由`java.lang.Thread`类或`java.util.concurrent.Executor`框架来创建。通过继承Thread类或实现Runnable接口,我们可以创建自己的线程。例如,当我们实现Runnable接口时,我们需要重写`run()`方法,该方法...

    Java线程(第三版)

    书中还可能涉及异常处理和线程中断,`interrupt()`方法用于标记线程中断状态,`isInterrupted()`和`InterruptedException`用于检查和处理中断。中断机制是Java中优雅停止线程的关键。 另外,Java并发工具库(java....

    java程序 两个线程实现学生成绩的读写

    在实际编程中,还需要考虑异常处理,防止线程中断或其他异常情况导致程序崩溃。 在设计这样的程序时,我们需要注意以下几个关键点: 1. **数据同步**:确保在读写操作时对共享数据的访问是安全的,避免数据不一致...

    JAVA多线程编程技术PDF

    此外,还有java.util.concurrent工具包,包含如BlockingQueue等高级并发结构,它们简化了线程间的协作和数据传递。 死锁是多线程中的一个常见问题,当两个或更多线程相互等待对方释放资源而无法继续执行时,就会...

    java Thread & synchronized & concurrent 线程、同步、并发

    为了解决这一问题,Java提供了更细粒度的锁,如`java.util.concurrent.locks.ReentrantLock`,它具有与`synchronized`相似的功能,但提供了更多的灵活性,如可中断的等待、定时等待和尝试获取锁。 此外,`java.util...

    Java多线程技术精讲

    创建Java线程主要有两种方式:继承Thread类和实现Runnable接口。继承Thread类可以直接重写run()方法,而实现Runnable接口则需要提供一个包含业务逻辑的run()方法,并通过构造Thread对象传入该Runnable实例。后者更为...

    java线程入门,java线程入门

    Java线程是多任务编程的...深入学习Java线程,不仅需要理解以上基本概念,还要熟悉线程池的使用、死锁和活锁的预防、线程中断机制、线程安全类库如Concurrent包等。通过实际项目中的实践,才能更好地掌握Java线程编程。

    Java多线程编程

    Java并发包(`java.util.concurrent`)提供了一系列高级并发工具,如`Semaphore`(信号量)、`CyclicBarrier`(循环屏障)、`CountDownLatch`(倒计时器)和`ExecutorService`等,它们可以帮助开发者更有效地管理线程...

    java 多线程课件

    抢占式调度意味着高优先级的线程可以中断正在执行的低优先级线程。Java提供了getPriority()和setPriority()方法来获取和设置线程优先级,优先级范围从MIN_PRIORITY(最低)到MAX_PRIORITY(最高),NORM_PRIORITY是...

    java中的多线程实例详解(自己去运行看结果)

    创建Java线程有多种方式: 1. 继承`Thread`类:创建一个新的类,继承自`Thread`,然后重写`run()`方法。创建实例后,调用`start()`启动线程。 2. 实现`Runnable`接口:创建一个实现`Runnable`接口的类,实现`run()`...

    java多线程控制的赛跑程序

    - Java线程有优先级设置,可以使用`setPriority()`方法调整。在赛跑中,优先级高的线程可能意味着选手跑得更快,但这并不总是意味着线程会先执行,因为线程调度由JVM决定。 5. **线程池**: - 为了更高效地管理...

    精通java多线程

    Java线程有五种状态:新建、可运行、运行、阻塞和终止。理解这些状态有助于我们更好地控制和调试多线程程序。 四、线程同步 线程同步是防止多个线程同时访问共享资源导致数据不一致的重要机制。Java提供了多种同步...

Global site tag (gtag.js) - Google Analytics