码迷,mamicode.com
首页 > 编程语言 > 详细

并发编程003 --- 线程的取消与关闭

时间:2019-10-05 12:59:49      阅读:120      评论:0      收藏:0      [点我收藏+]

标签:封装库   rri   mic   produce   vol   生效   not   清除   volatile   

要使线程安全、快速、可靠的停下来并非易事,java并未提供机制保证线程安全的停止,但是我们可以通过使用中断来完成线程的停止和关闭;

本章节只总结基础线程的取消和关闭,类似封装库提供的方法如Future、线程池不在本章节讨论。

1、interrupted方法

Thread提供了中断相关的方法,这里需要注意的一点是,使用静态的interrupted方法,会清除线程的中断状态

技术图片

 

 技术图片

 

 2、利用volatile变量作为标记,实现线程的关闭,前提是当前线程调用BlockingQ的produce方法,不会进入等待状态。

public class Producer implements Runnable {
    private volatile boolean canceled = false;

private BlockingQ blockingQ;

public Producer(BlockingQ blockingQ) {
this.blockingQ = blockingQ;
}

@Override
public void run() {
while (!canceled) {
blockingQ.produce();
}
}

public void cancel() {
this.canceled = true;
}
}
 

3、使用中断方法,实现线程终止或者关闭

上述方法在一定场景下可以保证线程安全的终止,但是对于处于等待状态下的线程,上述方法是不生效的,因为当前线程无法重新检查取消标记

此时需要使用Thread类的中断方法,实现一个更为健壮的线程取消方法,通常,阻塞方法object.wait(), Thread.sleep(), Thread.join()都会检查

线程中断状态,如果处于中断状态,会清除中断状态,并抛出InterruptedException异常,此时线程并未被真正的中断

下面的代码不会正常的关闭线程:由于清除了中断状态并在代码中捕获了该异常;外层判断中断状态时,线程一直执行;

正确的方法是在外层捕获异常

    public void produce() {
        Integer value = new Random().nextInt();

        synchronized (lock) {
            while (this.valueList.size() >= MAX_SIZE) {
                System.out.println("Thread " + Thread.currentThread().getName() + " produce wait.");
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    System.out.println("Thread " + Thread.currentThread().getName() + " Produce interrupted!!");
                    System.out.println(Thread.currentThread().isInterrupted());
                }
            }

            System.out.println("Thread " + Thread.currentThread().getName() + " produce value.");
            this.valueList.add(value);
            lock.notifyAll();
        }
    }
public class Producer implements Runnable {

    private BlockingQ blockingQ;

    public Producer(BlockingQ blockingQ) {
        this.blockingQ = blockingQ;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
        while (!Thread.currentThread().isInterrupted()) {
            blockingQ.produce();
        }
    }
}

错误的执行结果:

技术图片

正确示例:

    public void produce() throws InterruptedException {
        Integer value = new Random().nextInt();

        synchronized (lock) {
            while (this.valueList.size() >= MAX_SIZE) {
                System.out.println("Thread " + Thread.currentThread().getName() + " produce wait.");
                lock.wait();
            }

            System.out.println("Thread " + Thread.currentThread().getName() + " produce value.");
            this.valueList.add(value);
            lock.notifyAll();
        }
    }
public class Producer implements Runnable {

    private BlockingQ blockingQ;

    public Producer(BlockingQ blockingQ) {
        this.blockingQ = blockingQ;
    }

    @Override
    public void run() {
        try {
            while (!Thread.currentThread().isInterrupted()) {
                blockingQ.produce();
            }
        } catch (InterruptedException ex) {
            System.out.println(Thread.currentThread().getName() + " interrupted!!");
        }
    }
}

正确的执行结果:

技术图片

 

并发编程003 --- 线程的取消与关闭

标签:封装库   rri   mic   produce   vol   生效   not   清除   volatile   

原文地址:https://www.cnblogs.com/sniffs/p/11624179.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!