使用volatile类型的域来保存取消状态
因为volatile本身特性,每次修改都会立刻刷新到缓存中,这样就可以保证线程任务可以及时看到
下面代码示例,在线程运行一秒后取消任务:
public class PrimeGenerator implements Runnable{
private final List<BigInteger> primes = new ArrayList<>();
private volatile boolean cacelled;
@Override
public void run() {
BigInteger p = BigInteger.ONE;
while (!cacelled) {
p = p.nextProbablePrime();
primes.add(p);
}
}
public void cancel() {
cacelled = true;
}
public synchronized List<BigInteger> get() {
return new ArrayList<>(primes);
}
List<BigInteger> aSecondOfPrimes() {
PrimeGenerator generator = new PrimeGenerator();
new Thread(generator).start();
try {
SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return generator.get();
}
}
但是这种方式有一个问题:如果任务调用阻塞方法而被阻塞,那么现成永远都不会结束
如下面代码所示:
public class BrokenPrimeProducer extends Thread{
private final BlockingQueue<BigInteger> queue;
private volatile boolean cancelled = false;
public BrokenPrimeProducer(BlockingQueue<BigInteger> queue) {
this.queue = queue;
}
public void run() {
BigInteger p = BigInteger.ONE.ONE;
while(!cancelled) {
try {
queue.put(p = p.nextProbablePrime());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void cancel() {
cancelled = true;
}
public static void main(String[] args) {
BlockingQueue<BigInteger> primes = new ArrayBlockingQueue<BigInteger>(4);
BrokenPrimeProducer brokenPrimeProducer = new BrokenPrimeProducer(primes);
brokenPrimeProducer.start();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
brokenPrimeProducer.cancel();
System.out.println(brokenPrimeProducer.queue.size());
}
}
2.采用中断取消任务
设置中断后线程会抛出异常,这时候可以做相应处理然后退出任务
public class PrimeProducer extends Thread{
private final BlockingQueue<BigInteger> queue;
private volatile boolean cancelled = false;
public PrimeProducer(BlockingQueue<BigInteger> queue) {
this.queue = queue;
}
public void run() {
BigInteger p = BigInteger.ONE.ONE;
while(!Thread.currentThread().isInterrupted()) {
try {
queue.put(p = p.nextProbablePrime());
} catch (InterruptedException e) {
//这里接受中断异常,然后就可以退出线程
System.out.println(this.isInterrupted());
this.interrupt();
System.out.println(this.isInterrupted());
}
}
}
public void cancel() {
interrupt();
}
public static void main(String[] args) {
BlockingQueue<BigInteger> primes = new ArrayBlockingQueue<BigInteger>(4);
PrimeProducer brokenPrimeProducer = new PrimeProducer(primes);
brokenPrimeProducer.start();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
brokenPrimeProducer.cancel();
System.out.println(brokenPrimeProducer.queue.size());
}
}
3.stop结束线程
这种方法强制结束线程不推介使用