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

版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/sxj159753/article/details/78607113

在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知道该如何中断执行任务的线程;

猜你喜欢

转载自blog.csdn.net/sxj159753/article/details/78607113
今日推荐