java线程之线程中断的用处

引入线程中断用处的背景:

需要以协调的形式来实现任务的取消


一种简单的线程取消方法

public class SimpleThreadCancel {
	
	public static void main(String[] args) {
		CancelableTask task = new CancelableTask();
		task.start();
		try {
			Thread.sleep(5000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		} // 5秒后结束任务
		task.cancel();
	} 

}

class CancelableTask extends Thread {
	
	private volatile boolean cancel = false;
	
	public void run() {
		while(!cancel) {
			try {
				System.out.println("做任务");
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println("任务被取消");
	}
	
	public void cancel() {
		this.cancel = true;
	}
}

但是这里存在一个问题,假如任务被阻塞住,那么取消动作并不能让while循环退出

例子如下:

生产者不断往队列中存放东西,直到队列满了被阻塞,阻塞在queue.put(),此时执行的取消动作再也不能执行到,程序将一直阻塞,除非队列能够被消耗(即有quue.take()操作被执行)。

public class BlockingCancel {
	
	public static void main(String[] args) {
		BlockingQueue<Object> queue = new ArrayBlockingQueue<>(10);
		Producer p = new Producer(queue);
		p.start();
		try {
			Thread.sleep(5000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			p.cancel();
		}
	}

}

class Producer extends Thread {
	
	private BlockingQueue<Object> queue;
	private volatile boolean cancel;
	
	public Producer(BlockingQueue<Object> queue) {
		this.queue = queue;
	}
	
	@Override
	public void run() {
		while(!cancel) {
			try {
				this.queue.put("ddd");
				System.out.println("往队列生产了一个东西,队列size: " + this.queue.size());
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println("退出生产");
	}
	
	public void cancel() {
		this.cancel = true;
		System.out.println("执行了cancel操作");
	}
	
}


所以对于线程任务中有阻塞操作的取消,必须依赖于线程中断来实现,执行线程中断,可以跳出阻塞状态并执行中断处理,是否取消任务就取决于你如果处理中断,可以在中断处进行任务取消处理,及时退出循环。

你可能感兴趣的:(java,线程)