虽然Thread.stop和suspend等方法提供了线程终止的机制,但由于存在一些严重的缺陷,因此应该避免使用。可以说Java并没有提供任何机制来安全地终止线程。但它提供了中断(Interrupt),这时一种协作机制,能够使一个线程终止另一个线程的当前工作。
提到中断,我们就不得不说明一下Thead.interrupt方法:调用interrupt并不意味着立即停止目标线程正在进行的工作,而只是传递了请求中断的消息。
请看下面一个程序:
Thread t = new Thread(new Runnable(){ @Override public void run() { long i = 0; while(true) { System.out.println(i++); try { Thread.sleep(1000); } catch (InterruptedException e) { System.out.println(Thread.currentThread().isInterrupted()); Thread.currentThread().interrupt(); System.out.println(Thread.currentThread().isInterrupted()); e.printStackTrace(); } } } }); t.start(); try { Thread.sleep(3000); t.interrupt(); } catch (InterruptedException e) { e.printStackTrace(); }
哪怕在主线程中调用了t.interrupt()这个方法,但是t线程并不会停止执行,还是会无线执行下去。因为这个方法只是发送了一个消息给t线程,而t线程内部也只是将该线程的状态设置为了中断,这个状态可以通过Thead.isInterrupted或者静态方法interrupted来得到(如果已经中断,那么得到的是true)。
对中断操作的正确理解是:它并不会真正地中断一个正在运行的线程,而只是发出中断请求,然后由线程在下一个合适的时刻中断自己。
关于中断有两个地方需要注意:
- 一是捕获了InterruptedException异常,在JVM内部捕获到该异常以后会马上清除中断状态,也就是说调用Thead.isInterrupted得到将会是false
- 二是调用了静态方法interrupted,这个静态方法也会清除中断状态,如果仅仅要得到当前的状态信息,请使用Thead.isInterrupted
需要注意:只有当线程在阻塞状态下发生中断时,才会抛出InterruptedException异常,这里所说的阻塞状态包括三种情况:
- wait
- sleep
- join
在非阻塞状态下中断时,仅仅它的中断状态会被设置,并不会触发InterruptedException异常,这里和别的异常不一样,你要是在非阻塞状态下手工捕获这个异常,编译是通不过的。会提示:Unreachable catch block for InterruptedException. This exception is never thrown from the try statement body。 而捕获别的异常不会有这种情况。
这时候你就要在线程中自己来判断中断状态,比如下面这个程序,在每次循环的开始部分都判断当前的中断状态,当状态改变时,线程结束:
Runnable task = new Runnable() { @Override public void run() { while(!Thread.currentThread().isInterrupted()) { System.out.println(1); } } };
通常,中断是实现取消的最合理方式,不要使用boolean标志来请求取消。
有人会说了,interrupt方法是Thread的方法,而我们在使用Executor框架执行任务的时候经常会使用Runnable。这时,我们就无法使用中断方法来取消了。这个时候我们可以使用Future来实现取消,查看API你会发现Future有一个cancel方法,再去查看源码,下面是cancle方法的内部实现:
boolean innerCancel(boolean mayInterruptIfRunning) { for (;;) { int s = getState(); if (ranOrCancelled(s)) return false; if (compareAndSetState(s, CANCELLED)) break; } if (mayInterruptIfRunning) { Thread r = runner; if (r != null) r.interrupt(); } releaseShared(0); done(); return true; }
我们可以发现,它也是通过中断线程来实现的,所以要真正的取消任务还是要在每个任务中实现自己的中断策略。
因此:由于每个线程拥有各自的中断策略,因此除非你直到中断对该线程的含义,否则就不应该中断这个线程。没有实现中断策略的任务哪怕你调了cancel方法也是无法中断这个线程的。比如下面这个非阻塞任务(阻塞任务必定会抛出InterruptedException,一般都会实现中断策略的):
ExecutorService executorService = Executors.newFixedThreadPool(10); Runnable task = new Runnable() { @Override public void run() { while(true) { System.out.println(1); } } }; Future<?> future = executorService.submit(task); Thread.sleep(2000); future.cancel(true);
这个程序哪怕被cancel了,其实也是一直会print出字符的。
你可以这么写,在规定的三秒钟之内没有执行完任务(这个程序只要不中断,必然不会执行完,是一个死循环),那么主线程就会取消它:ExecutorService executorService = Executors.newFixedThreadPool(10); Runnable task = new Runnable() { @Override public void run() { while(!Thread.currentThread().isInterrupted()) { System.out.println(1); } } }; Future<?> future = executorService.submit(task); try { future.get(3, TimeUnit.SECONDS); } catch (ExecutionException e) { e.printStackTrace(); } catch (TimeoutException e) { e.printStackTrace(); } finally{ future.cancel(true); }
相关推荐
在Java并发编程中,线程的关闭和取消是一项重要的任务,因为不正确的处理可能导致数据不一致、资源泄漏等问题。在Java中,强制停止线程并不是一个推荐的做法,因为这可能会导致系统状态的不稳定。传统的`Thread.stop...
在嵌入式系统开发中,中断驱动程序是操作系统与硬件交互的关键部分,它使得硬件能够及时、高效地向处理器发送事件通知。S3C6410是一款由Samsung生产的高性能ARM11架构的微处理器,广泛应用于嵌入式设备中。在本主题...
"Exp2-ARM-serial-interrupt.zip" 文件包含了一个ARM架构下实现串口中断的实验,下面将详细介绍相关的知识点。 1. **串口通信**: - **UART(通用异步收发传输器)**:是串口通信的基础,负责将并行数据转换为串行...
3. **取消与重试策略**:如果任务需要取消,可以考虑设计重试机制,让任务在合适的时候重新启动。 4. **理解生命周期**:AsyncTask与Activity的生命周期紧密关联。当Activity结束时,应取消相关的AsyncTask,以防止...
否则,它将抛出一个`TimeoutException`,此时可以取消任务。 另外,`java.lang.Thread`类也提供了一种实现线程超时的方法,通过使用`join`方法。`join`可以等待某个线程结束,同时可以设置一个等待时限。 ```java ...
Future对象可以用来检查任务是否完成,如果超过预定时间,可以调用`cancel()`方法来取消任务。 ```java ExecutorService executor = Executors.newSingleThreadExecutor(); Future<String> future = executor....
- 取消任务:`cancel()`方法尝试取消任务,如果任务已经开始则可能无法取消。 6. **ExecutorService管理** - 创建:`Executors`工厂类提供多种ExecutorService实例。 - 分配任务:使用`execute()`方法提交...
"rg_interrupt"这个主题可能指的是一个特定的项目或者库,它与Python编程语言中的中断处理有关。在Python中,处理中断(例如键盘中断Ctrl+C)通常涉及到异常处理和线程管理。 在Python中,中断通常是通过`...
2. **`submit(Runnable task)`**:这个方法同样用于提交一个`Runnable`任务,但它返回一个`Future`对象,可以通过该对象来获取任务执行的结果或取消任务的执行。 ### `execute()`方法的执行流程 当调用`execute()`...
但是,这种方法忽略了这样一个事实:这期间可能发生中断,而中断可能导致应用程序丧失及时取消活动或关闭的能力。因此,正确地处理 InterruptedException 是非常重要的。 中断状态是每个线程都有的一个 Boolean ...
- 通常,我们会为每个goroutine提供一个可以被关闭的`context.Context`,当需要停止服务时,通过这个`Context`来取消任务。 - 示例代码: ```go func startService() { ctx, cancel := context.WithCancel...
当一个线程需要被取消时,可以调用interrupt方法。然而,线程本身需要检查并响应中断状态,以确保正确关闭。 10. **ThreadLocal** ThreadLocal是Java提供的一个线程局部变量,每个线程都有自己的副本,互不影响,...
中断服务上半部(Interrupt Service Routine,ISR)是中断发生时立即执行的代码,它的主要任务是保存现场、关闭中断、识别中断源并做一些快速的、必须在原子操作下完成的处理。然而,有些操作不适合在ISR中执行,...
综上所述,RTAI文档中的源代码说明部分详细阐述了RTAI在x86架构下如何进行中断处理、中断的启动和关闭、中断源的管理,以及如何与标准Linux内核集成的一系列API函数。同时,文档强调了RTAI作为开源软件的许可条款和...
`Future`接口代表`Callable`任务的结果,可以检查任务是否完成,获取结果或取消任务。例如: ```java ExecutorService executor = Executors.newSingleThreadExecutor(); Future<Integer> future = executor.submit...
这样,当新Activity关闭时,整个任务栈都会被清理,从而结束应用进程。 在实际开发中,除非有特殊需求,否则通常不建议强行结束应用进程,因为Android系统会根据资源需求自动管理进程。过度干预可能会导致系统不...
使用`context.Context`可以帮助管理上下文和取消信号,而`net/http.Server`提供了优雅停机的选项,可以在接收到信号后等待已接收的请求完成后再关闭服务器。 总之,优雅的进程重启是维持服务稳定性的重要手段,它...
- **Future/Tasks**:使用ExecutorService提交任务,调用Future的cancel()方法请求取消,线程会尝试停止。 5. **线程池与线程终止** - **ThreadPoolExecutor**:可以设置核心线程存活策略、最大线程数、超时策略...
在实际的并发编程中,线程中断常用于取消任务、响应外部事件或者优雅地关闭资源。它与`Thread.stop()`方法不同,后者是不推荐使用的,因为它可能导致数据损坏和死锁。线程中断是一种更加安全和推荐的方式来控制线程...