java并发编程实战:取消与关闭笔记

来源:互联网 发布:houdini编程 编辑:程序博客网 时间:2024/05/22 12:02

在Java中无法抢占式地停止一个任务的执行,而是通过中断机制实现了一种协作式的方式来取消任务的执行。

设置取消标志

public class MyTask implements Runnable {    private final ArrayList<BigInteger> primes = new ArrayList<BigInteger>();    private volatile boolean cancelled;    @Override    public void run() {        while (!cancelled) {          ...        }    }    public void cancel() {        cancelled = true;    }}

中断线程的执行

 public static boolean interrupted() {        return currentThread().isInterrupted(true);    }    public boolean isInterrupted() {        return isInterrupted(false);    }    private native boolean isInterrupted(boolean ClearInterrupted);

interrupt方法试图中断线程并设置中断状态标志变量为true;
isInterrupted方法测试线程是否已经中断,返回中断状态变量的值;
interrupted方法用于清除线程的中断状态,并返回之前的值,即如果当前线程是中断状态,则重新设置为false,并且返回true;

调用interrupt并不意味着必然停止目标线程工作,它紧紧传递了请求中断信息。

阻塞方法与线程的中断

大部分的阻塞方法都是响应中断的,即这些方法在线程中执行时如果发现线程被中断,会清除线程的中断状态,并抛出InterruptedException表示该方法的执行过程被从外部中断。响应中断的阻塞方法通常会在入口处先检查线程的中断状态,线程不是中断状态时,才会继续执行。

class PrimeProducer extends Thread{        private final BlockingQueue<BigInteger> queue;        private volatile boolean cancelled;        PrimeProducer(BlockingQueue<BigInteger> queue){            this.queue = queue;        }        public void run(){            BigInteger p = BigInteger.ONE;            while(!Thread.currentThread().isInterrupted(){                queue.put(p = p.nextProbablePrime());                }catch(InterruptedException consumed){                    /*允许线程退出*/                }            }        public void cancel(){            interrupt();        }}

中断响应

当调用可中断的阻塞方法时,有两种策略可用于处理InterruptedException
1、传递异常,从而使你的方法也成为可中断的阻塞方法。
2、恢复中断状态,从而使调用栈上中的上层代码能够对其进行处理。
只有实现了线程中断策略的代码才可以屏蔽中断请求,常规任务中不应该屏蔽中断请求。

通过Future实现取消

public class TimedRun {    private static final ExecutorService taskExec = Executors.newCachedThreadPool();    public static void timedRun(Runnable r,                                long timeout, TimeUnit unit)            throws InterruptedException {        Future<?> task = taskExec.submit(r);        try {            task.get(timeout, unit);        } catch (TimeoutException e) {            // task will be cancelled below        } catch (ExecutionException e) {            // exception thrown in task; rethrow            throw launderThrowable(e.getCause());        } finally {            // Harmless if task already completed            task.cancel(true); // interrupt if running        }    }}

Future接口有一个cancel方法,可以通过该方法取消任务的执行,cancel方法有一个boolean型的参数mayInterruptIfRunning。

如果设置为false,对于正在执行的任务只能等到任务执行完毕,无法中断;

如果设置为true,对于正在执行的任务可以试图中断任务的运行,这种情况通常只在与Executor框架配合时使用,因为执行任务的线程是由Executor创建的,Executor知道该如何中断执行任务的线程;

原创粉丝点击