<<java并发编程>>读书笔记之线程中断


public class PrimeGenerator implements Runnable {

private final List<BigInteger> list = new ArrayList<BigInteger>();

private volatile boolean cancell;

@Override
public void run() {
BigInteger big = BigInteger.ONE;
while (!cancell) {
big = big.nextProbablePrime();
synchronized (list) {
list.add(big);
}
}
}

public List<BigInteger> get() {
synchronized (list) {
return new ArrayList<BigInteger>(list);
}
}

public void setCancell(boolean cancell) {
this.cancell = cancell;
}

public List<BigInteger> aSecondOfPrimer(PrimeGenerator p) throws Exception {
new Thread(p).start();
try {
Thread.sleep(10);
} finally {
this.setCancell(true);
}
return p.get();

}

public static void main(String[] args) throws Exception {
PrimeGenerator p = new PrimeGenerator();
System.out.println(p.aSecondOfPrimer(p));

}

}


最简单的中断方式,使用一个volatile的boolean变量,控制终止。但是不一定signal后就会马上终止,可能在在执行run的一些代码的时候,会出现延迟,甚至会出错。
不过我们把signal放在finally块中,保证一定会执行。
有的时候,这种方式不一定就是安全的,例如有一些类自身就有阻塞的行为,例如BlockingQueue类型,从以下代码可以看出:

package com.test.db;

import java.math.BigInteger;
import java.util.concurrent.BlockingQueue;

public class BlockTest implements Runnable {

private final BlockingQueue<BigInteger> queue = new ArrayBlockingQueue<BigInteger>(
1);
private volatile boolean cancell;

// 生产者线程
@Override
public void run() {
BigInteger big = BigInteger.ONE;
while (!cancell) {
try {
queue.put(big=big.nextProbablePrime());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

public void setInterrupted() {
cancell = true;
}

public void consumer(BlockTest b) {
new Thread(b).start();
try {
while (true)
try {
System.out.println(queue.take());
//System.out.println("size :"+queue.size());
} catch (InterruptedException e) {
e.printStackTrace();
}
} finally {
b.setInterrupted();
}

}

public static void main(String[] args) {
BlockTest b = new BlockTest();
b.consumer(b);
}

}


为什么说这是unreliable,我们可以看一下ArrayBlockingQueue的源代码,先看一下put

public void put(E e) throws InterruptedException {
if (e == null) throw new NullPointerException();
final E[] items = this.items;
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
try {
while (count == items.length)
notFull.await();
} catch (InterruptedException ie) {
notFull.signal(); // propagate to non-interrupted thread
throw ie;
}
insert(e);
} finally {
lock.unlock();
}
}

我们指定的capacity的是1,也就是当count和items.length相等的时候,这个queue会被阻塞。
问题就在于:当生产者线程的put>take,这个时候queue会被很快填满.此时如果take速度比较慢,并且signal中断,这个时候是没有办法停止的,除非当take到最后一个的时候,该线程才会退出。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值