精华内容
下载资源
问答
  • Java线程中断机制-如何中断线程.pdf
  • JAVA线程中断

    千次阅读 2018-12-11 18:40:44
    判断线程是否被中断 while(!Thread.currentThread().isInterrupted() && more work to do){ do more work } JDK源代码分析 public void interrupt() { //如果不是本线程,那么需要检查是否拥有...

    几个API

    判断线程是否被中断

    while(!Thread.currentThread().isInterrupted() && more work to do){
        do more work
    }
    

    JDK源代码分析

        public void interrupt() {
            //如果不是本线程,那么需要检查是否拥有权限。如果没有,抛出SecurityException
            if (this != Thread.currentThread())
                checkAccess();
    
            synchronized (blockerLock) {//本线程对象所持有的锁,用于防止并发出错。
                Interruptible b = blocker;
                if (b != null) {
                    interrupt0();           // Just to set the interrupt flag(设置标识位,native方法)
                    b.interrupt(this);//真正打断进程的方法
                    return;
                }
            }
            interrupt0();
        }
    
        // 静态方法,这个方法有点坑,调用该方法调用后会清除中断状态。
        public static boolean interrupted() {
            return currentThread().isInterrupted(true);
        }
        // 这个方法不会清除中断状态
        public boolean isInterrupted() {
            return isInterrupted(false);
        }
       // 上面两个方法会调用这个本地方法,参数代表是否清除中断状态
       private native boolean isInterrupted(boolean ClearInterrupted);
    

    中断机制

    如果线程被interrupt,大概有这么几种情况。

    • 如果线程堵塞在object.wait、Thread.join和Thread.sleep,将会清除线程的中断状态,并抛出InterruptedException;

    • 如果线程堵塞在java.nio.channels.InterruptibleChannel的IO上,Channel将会被关闭,线程被置为中断状态,并抛出java.nio.channels.ClosedByInterruptException;

    • 如果线程堵塞在java.nio.channels.Selector上,线程被置为中断状态,select方法会马上返回,类似调用wakeup的效果;

    • 如果不是以上三种情况,thread.interrupt()方法仅仅是设置线程的中断状态为true。

    下面代码中的t1线程将永远不会被中断。程序永远不会退出。

    public class ThreadInterruptTest {
        static long i = 0;
        public static void main(String[] args) {
            System.out.println("begin");
            Thread t1 = new Thread(new Runnable() {
                @Override
                public void run() {
                    while (true){
                        i++;
                        System.out.println(String.valueOf(i));
                    }
                }
            });
            t1.start();
            t1.interrupt();
        }
    }
    

    java的线程中断,在线程没有阻塞的情况下,是通过标识位实现的,依赖于程序员自己检查。那么,对于阻塞的线程,JVM又是如何处理的呢?
    很简单,就是设置中断状态,然后唤醒线程。让线程重新工作而已。

    void os::interrupt(Thread* thread) {
      assert(Thread::current() == thread || Threads_lock->owned_by_self(),
        "possibility of dangling Thread pointer");
      //获取本地线程对象
      OSThread* osthread = thread->osthread();
      if (!osthread->interrupted()) {//判断本地线程对象是否为中断
        osthread->set_interrupted(true);//设置中断状态为true
        // More than one thread can get here with the same value of osthread,
        // resulting in multiple notifications.  We do, however, want the store
        // to interrupted() to be visible to other threads before we execute unpark().
        //这里是内存屏障,内存屏障的目的是使得interrupted状态对其他线程立即可见
        OrderAccess::fence();
        //_SleepEvent相当于Thread.sleep,表示如果线程调用了sleep方法,则通过unpark唤醒
        ParkEvent * const slp = thread->_SleepEvent ;
        if (slp != NULL) slp->unpark() ;
      }
      // For JSR166. Unpark even if interrupt status already was set
      if (thread->is_Java_thread())
        ((JavaThread*)thread)->parker()->unpark();
      //_ParkEvent用于synchronized同步块和Object.wait(),这里相当于也是通过unpark进行唤醒
      ParkEvent * ev = thread->_ParkEvent ;
      if (ev != NULL) ev->unpark() ;
    }
    

    中断的使用

    中断是实现任务取消的最合理的方式。在广泛接受的编程规范,中断处理应该尽可能迅速。一般而言,我们提供的库不应该捕获中断,而是应该直接抛出中断让调用者决定。

    展开全文
  • Java 线程中断

    千次阅读 2017-08-26 13:08:13
    一个线程在未正常结束之前, 被强制终止是很危险的事情. 因为它可能带来完全预料不到的严重后果.... 优雅的方法就是, 给那个线程一个中断信号, 让它自己决定该怎么办. 比如说, 在某个子线程中为了...

    一个线程在未正常结束之前, 被强制终止是很危险的事情. 因为它可能带来完全预料不到的严重后果. 所以你看到Thread.suspend, Thread.stop等方法都被Deprecated了.
    那么不能直接把一个线程搞挂掉, 但有时候又有必要让一个线程死掉, 或者让它结束某种等待的状态 该怎么办呢? 优雅的方法就是, 给那个线程一个中断信号, 让它自己决定该怎么办. 比如说, 在某个子线程中为了等待一些特定条件的到来, 你调用了Thread.sleep(10000), 预期线程睡10秒之后自己醒来, 但是如果这个特定条件提前到来的话, 你怎么通知一个在睡觉的线程呢? 又比如说, 主线程通过调用子线程的join方法阻塞自己以等待子线程结束, 但是子线程运行过程中发现自己没办法在短时间内结束, 于是它需要想办法告诉主线程别等我了. 这些情况下, 就需要中断. 

    中断是通过调用Thread.interrupt()方法来做的. 这个方法通过修改了被调用线程的中断状态来告知那个线程, 说它被中断了. 对于非阻塞中的线程, 只是改变了中断状态, 即Thread.isInterrupted()将返回true; 对于可取消的阻塞状态中的线程, 比如等待在这些函数上的线程, Thread.sleep(), Object.wait(), Thread.join(), 这个线程收到中断信号后, 会抛出InterruptedException, 同时会把中断状态置回为false.

    中断状态可以通过 Thread.isInterrupted()来读取,并且可以通过一个名为 Thread.interrupted()的静态方法读取和清除状态(即调用该方法结束之后, 中断状态会变成false)。
    由于处于阻塞状态的线程 被中断后抛出exception并置回中断状态, 有时候是不利的, 因为这个中断状态可能会作为别的线程的判断条件, 所以稳妥的办法是在处理exception的地方把状态复位:

    public class ThreadInterrupt extends Thread {
    
        @Override
        public synchronized void start() {
            super.start();
            System.out.println("ThreadInterrupt is start!");
        }
    
        public synchronized void  kill() {
            interrupt();
            System.out.println("ThreadInterrupt is kill!");
        }
    
        @Override
        public void run() {
            while (!Thread.currentThread().isInterrupted()) {
                try {
                    Thread.sleep(1000);  // 延迟50秒
                    System.out.println("ThreadInterrupt is runing!");
                } catch (InterruptedException e) {
                    interrupt();
                }
            }
        }
    }

     

    展开全文
  • java 线程中断

    千次阅读 2014-09-02 15:41:45
    java中断是一种中断机制 如果我们写的线程没有对中断请求进行响应 那么线程是无法被中断的。(这里说的是线程代码是指在子线程中运行的所有 方法代码。当然第一个方法就是Thread的run方法)

    java中断是一种中断机制 如果我们写的线程没有对中断请求进行响应那么线程是无法被中断的。(这里说的是线程代码是指在子线程中运行的所有方法代码。当然第一个方法就是Thread的run方法)

    示例代码:

    public class ThreadInterruptTest {
    
        //任务的阻塞队列
        BlockingQueue<Runnable> blockingQueue;
    
        public static void main(String[] args) {
    	ThreadInterruptTest test = new ThreadInterruptTest();
    	test.init();
        }
    
        /**
         *<p>TODO(概括性描述)</p><br/>
         *<p>TODO(详细描述)</p>
         * @since 2.6
         * @author liulp
         */
        private void init() {
    	// TODO Auto-generated method stub
    
    	//初始化阻塞队列
    	blockingQueue = new ArrayBlockingQueue<Runnable>(20);
    
    	Thread t = new Thread() {
    	    @Override
    	    public void run() {
    		// TODO Auto-generated method stub
    		super.run();
    
    		//从队列中取任务 然后执行 直到执行完任务
    		while (true) {
    
    		    MyRunnable run = (MyRunnable) blockingQueue.poll();
    		    if (run != null) {
    			System.out.println("task "+run.i+" start");
    
    			//执行任务
    			run.run();
    
    		    } else {
    			break;
    		    }
    		}
    	    }
    	};
    	
    	//添加10个任务
    	for (int i = 1; i <= 10; i++) {
    	    try {
    		blockingQueue.put(new MyRunnable(i));
    	    } catch (InterruptedException e) {
    		// TODO Auto-generated catch block
    		e.printStackTrace();
    	    }
    	}
    	//启动线程
    	t.start();
    
    	//中断线程
    	t.interrupt();
    	
    	//继续添加任务
    	blockingQueue.add(new MyRunnable(11));
    
        }
    
        class MyRunnable implements Runnable {
    
    	int i;
    
    	/**
    	 * 
    	 */
    	public MyRunnable(int i) {
    	    // TODO Auto-generated constructor stub
    	    this.i = i;
    	}
    
    	@Override
    	public void run() {
    	    int m = 0;
    	    int a = 0;
    	    
    	    //消耗CP时间
    	    for (; m < Integer.MAX_VALUE; m++) {
    		a++;
    	    }
    
    	    System.out.println("Task " + i + " end");
    	}
        }
    
    }

    运行结果:

    task 1 start
    Task 1 end
    task 2 start
    Task 2 end
    task 3 start
    Task 3 end
    task 4 start
    Task 4 end
    task 5 start
    Task 5 end
    task 6 start
    Task 6 end
    task 7 start
    Task 7 end
    task 8 start
    Task 8 end
    task 9 start
    Task 9 end
    task 10 start
    Task 10 end
    task 11 start
    Task 11 end

    可以看到 虽然我们调用了线程的中断但是所有的任务都执行完毕了,甚至我们在调用中断后添加的任务也执行了。

    那么我们应该怎么样中断任务呢?

    我们知道java的线程中断时一种写作机制,并不是调用线程的中断方法 就可以中断线程,而是需要任务的执行者来响应中断才可以。

    我们稍微修改下MyRunnable的run方法来响应中断。

    public void run() {
    	    
    	    //如果有中断请求
    	    if(Thread.interrupted()){
    		//直接reutrn掉
    		return;
    	    }
    	    
    	    int m = 0;
    	    int a = 0;
    	    
    	    //消耗CP时间
    	    for (; m < Integer.MAX_VALUE; m++) {
    		a++;
    	    }
    
    	    System.out.println("Task " + i + " end");
    	}

    运行结果如下:

    task 1 start
    task 2 start
    Task 2 end
    task 3 start
    Task 3 end
    task 4 start
    Task 4 end
    task 5 start
    Task 5 end
    task 6 start
    Task 6 end
    task 7 start
    Task 7 end
    task 8 start
    Task 8 end
    task 9 start
    Task 9 end
    task 10 start
    Task 10 end
    task 11 start
    Task 11 end
    哦看起来好像没有什么变化,所有的任务都打印了,但是仔细看你会发现少了一句
    task 1 end
    这说明task 1的run方法没有执行完 而是return了。

    我们通过在run方法中检查中断状态中断了task 1的执行,但是其他的任务并没有被中断,这是因为调用thread.interrupted()会恢复状态中断,在线程中第二次调用

    interrupted() 就返回false了,如果我们想中断所有的任务怎么办呢?那只有想办法让线程完全终止,我们可以通过跑车一个Error 或是RuntimeExcepton终止线程的

    执行,我们再次修改 MyRunnable的run方法:

    @Override
    	public void run() {
    	    
    	    //如果有中断请求
    	    if(Thread.interrupted()){
    //		Error e =new Error("die");
    		RuntimeException e = new RuntimeException("die");
    		throw(e);
    	    }
    	    
    	    int m = 0;
    	    int a = 0;
    	    
    	    //消耗CP时间
    	    for (; m < Integer.MAX_VALUE; m++) {
    		a++;
    	    }
    
    	    System.out.println("Task " + i + " end");
    	}

    运行结果:

    task 1 start
    Exception in thread "Thread-0" java.lang.RuntimeException: die
        at com.popo.test.thread.ThreadInterruptTest$MyRunnable.run(ThreadInterruptTest.java:103)
        at com.popo.test.thread.ThreadInterruptTest$1.run(ThreadInterruptTest.java:56)
    

    线程完全被终止了,不过如果我们在Thread.run()方法中捕获RuntimeException线程也是不会被终止的,有兴趣的可以实现下。

    当然我们如果在执行任务队列是不应该中断其他任务的执行的,除非调用者有显示的调用(比如Executes.shutDownNow()方法 就是终止所有未完成的任务)

    最后加上一段 Thread.interrupt()方法的注释

    Posts an interrupt request to this Thread. The behavior depends on the state of this Thread:

    也就是说在上边两种阻塞情况下 线程会被唤醒 并抛出异常,我们可以通过捕获异常来响应中断。

    第三种情况会设置中断状态 并且selector马上返回但是不会收到异常。这种异常处理应该需要程序员自己去检查中断状态来响应中断。


    展开全文
  • 给大家分享了java线程中断的办法以及相关知识点内容,有需要的朋友们可以学习参考下。
  • Java线程中断

    2012-06-20 19:57:40
    Java线程中断采用类似CPU中断的思想。即Thread对象有一个int的标识,用来表示是否有中断发生。1表示有,0表示无。线程的代码检测中断标识,并做相应的处理。 1. 如何设置中断状态  如果需要设在中断标识为1,...

    Java的线程中断采用类似CPU中断的思想。即Thread对象有一个int的标识,用来表示是否有中断发生。1表示有,0表示无。线程的代码检测中断标识,并做相应的处理。

    1. 如何设置中断状态

         如果需要设在中断标识为1,那么调用Thread的interrupt方法。此方法仅仅设置中断标识为1,不做其他操作。

    2. 如何处理中断状态

         2.1 线程中正在运行的代码应该不停的检测是否发生中断,并做出相应的处理并重置中断标识为0。通常的情况是忽略中断,或者退出程序当有中断发生。

         2.2 线程中的代码正在阻塞(调用Object 类的 wait()wait(long)wait(long, int) 方法,Thread类的join()join(long)join(long, int)sleep(long)sleep(long, int)),当中断标识被置为1时,在代码阻塞出抛出中断异常并自动清除中断状态(重置中断标识为0)。线程代码应该对中断异常做出相应的出来。

         2.3 线程中的代码在可中断的资源上阻塞(NIO),当中断标识被置为1时,有两种情况(不自动清楚中断状态):

                1)可中断资源关闭,在代码阻塞处抛出资源关闭异常。

                2)立刻返回空结果。

              此时线程代码需要处理异常和中断。

    3. 清除中断状态

         调用Thread类的interrupted方法,该方法返回当前的中断状态,并重置中断标识为0

    4. 特殊阻塞的中断

       ServerSocket的accept方法一直阻塞,其方法本省不会出来中断。如果要中断阻塞,需要调用ServerSocket的close方法,此时accept方法中断阻塞并抛出IOException

    展开全文
  • 在本篇文章中我们给大家分享了关于Java线程中断的相关知识点内容以及相关代码实例,有兴趣的朋友们可以学习下。
  •   Java 中的线程中断是一种线程间的协作模式,通过设置线程的中断标志并不能直接终止该线程的执行,而是被中断的线程根据中断状态自行处理。即“线程中断”并不是字面意思——线程真的中断了,而是设置了中断标志...
  • 本篇文章对Java线程中断的本质与编程原则进行了详细的概述,需要的朋友参考下
  • Java中断是一种协作机制。也就是说调用线程对象的interrupt方法并不一定就中断了正在运行的线程,它只是要求线程自己在合适的时机中断自己,本文将详细介绍,需要了解的朋友可以参考下
  • java线程中断记录

    万次阅读 2020-04-03 22:03:42
    开发者使用多线程处理此类工作。由于此类工作十分耗时,用户有时忍受不了,直接停止该进程。如何做到呢? 2、模拟案例 假设有个耗时任务doSpendTimeThings,这是一个死循环,目的就是模拟耗时任务。 /** * 死循环 ,...
  • 最近学习了线程中断原理,由于线程在运行中,如果执行了sleep方法,会被trycatch捕获到,然后会出现中断方法的上层方法捕获不到,于是研究了下,发现下层方法里,中断后,被异常捕获,捕获后把线程中断信号清除了,做此文用来...
  • java 线程 中断标志位

    千次阅读 2018-05-19 12:19:00
    课程素材来自 http://enjoy.ke.qq.com/ 版权所有java线程中,线程中断方法详解:线程自然终止:自然执行完或抛出未处理异常stop(),resume(),suspend()已不建议使用,stop()会导致线程不会正确释放资源,suspend()...
  • java线程中断的问题。

    2017-02-28 15:54:06
    为什么在调用sleep或者wait方法之前改变线程中断状态,sleep也会抛出异常并将中断状态复位?
  • 深入分析Java线程中断机制

    千次阅读 2015-08-01 15:04:17
    在平时的开发过程中,相信都会使用到多线程,在使用多线程时,相信大家也会遇到各种各样的问题,今天我们就来说说一个多线程的问题——线程中断。在java中启动线程非常容易,大多数情况下我是让一个线程执行完自己的...
  • 很多Java开发人员(包括我),尤其是刚进入软件行业的新手,认为Java设置线程中断就是表示线程停止了,不往前执行了, Thread.currentThread().interrupt()  其实不是这样的,线程中断只是一个状态而已,true表示...
  • Java线程中断理解(interrupte)

    千次阅读 2015-08-12 14:11:43
    Java线程之中,一个线程的生命周期分为:初始、就绪、运行、阻塞以及结束。当然,其中也可以有四种状态,初始、就绪、运行以及结束。  一般而言,可能有三种原因引起阻塞:等待阻塞、同步阻塞以及其他阻塞(睡眠、...
  • 最近在学习JUC框架的时候,发现了很多工具类都是支持可中断的,如AQS、FutureTask都是可以在线程执行中,支持对于中断的响应,所以需要对线程中断有个了解,才能更好的学习JUC的源码。 线程中断的作用: 线程中断...
  • Java没有提供一种安全直接的方法来停止某个线程,但是Java提供了中断机制。 如果对Java中断没有一个全面的了解,可能会误以为被中断线程将立马退出运行,但事实并非如此。中断机制是如何工作的?捕获或检测到中断...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 155,306
精华内容 62,122
关键字:

java线程中断

java 订阅