在下面的示例中,我试图优雅地终止两个线程。消费者线程在休眠时被中断,这应该将isInterrupted标志设置为true。然而,!thread.currentThread()。isInterrupted()检查while循环仍然似乎返回= false,因为它不会终止使用者线程。
将以下代码复制并粘贴到IDE中以检查:
public class ThreadInterruptExample {
public static void main(String[] args) throws InterruptedException {
LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<String>(1);
ThreadInterruptExample ie = new ThreadInterruptExample();
Producer producer = ie.new Producer(queue);
Consumer consumer = ie.new Consumer(queue, producer);
producer.start();
consumer.start();
Thread.sleep(1000);
producer.cancel();
consumer.cancel();
}
class BaseQueue extends Thread {
protected final BlockingQueue<String> queue;
public BaseQueue(BlockingQueue<String> queue) {
this.queue = queue;
}
public void cancel() {
System.out.println(this.getName() + " - Shutting down");
interrupt();
}
}
class Producer extends BaseQueue {
private final List<String> messages = Arrays.asList("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q",
"r", "s", "t", "u", "v", "w", "x", "y", "z");
public Producer(BlockingQueue<String> queue) {
super(queue);
this.setName("Producer");
}
public void run() {
try {
for (String message : messages) {
System.out.println(this.getName() + ": Sending " + message);
queue.put(message);
}
} catch (InterruptedException e) {
System.out.println(this.getName() + " - InterruptedException occurred");
}
}
}
class Consumer extends BaseQueue {
private final BaseQueue producer;
public Consumer(BlockingQueue<String> queue, BaseQueue producerQueue) {
super(queue);
this.setName("Consumer");
producer = producerQueue;
}
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
System.out.println(this.getName() +": Consumer Running");
String message = "";
try {
Thread.sleep(1500);
message = queue.take();
System.out.println(this.getName() + ": Recevied " + message);
if (message.equals("pill")) {
producer.cancel();
this.cancel();
}
} catch (InterruptedException e) {
System.out.print(this.getName() + ": Exception occurred for: " + message);
e.printStackTrace();
}
}
}
}
}
答案 0 :(得分:3)
当您捕获InterruptedException时,您正在丢弃中断。有两种解决方案。
while (!Thread.currentThread().isInterrupted()) {
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
Thread.currentThread.interrupt();
}
}
或更简单的是只捕获循环外的异常。
try {
while (!Thread.currentThread().isInterrupted()) {
Thread.sleep(1500);
}
} catch (InterruptedException e) {
Thread.currentThread.interrupt();
}
编辑:我认为这只是一个练习,因为使用ExecutorService会更简单
public static void main(String[] args) throws InterruptedException {
ExecutorService service = Executors.newSingleThreadExecutor();
for (String message : "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z".split(",")) {
System.out.println(getThreadName() + ": Sending " + message);
service.submit(() -> {
System.out.println(getThreadName() + ": Recevied " + message);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
System.out.println("--- Interrupted");
}
});
}
service.shutdown();
service.awaitTermination(1, TimeUnit.SECONDS);
service.shutdownNow();
}
public static String getThreadName() {
return Thread.currentThread().getName();
}
打印
main: Sending a
main: Sending b
main: Sending c
main: Sending d
main: Sending e
main: Sending f
main: Sending g
main: Sending h
main: Sending i
main: Sending j
main: Sending k
main: Sending l
main: Sending m
main: Sending n
main: Sending o
main: Sending p
main: Sending q
main: Sending r
main: Sending s
main: Sending t
main: Sending u
main: Sending v
main: Sending w
main: Sending x
main: Sending y
main: Sending z
pool-1-thread-1: Recevied a
pool-1-thread-1: Recevied b
--- Interrupted
答案 1 :(得分:1)
如果在调用Object类的wait(),wait(long)或wait(long,int)方法,或者join(),join(long),join(long)时阻塞了这个线程,int),sleep(long)或sleep(long,int),这个类的方法,然后它的中断状态将被清除,它将收到InterruptedException。
因此,在您调用中断时消费者正在休眠状态,中断状态被清除,您收到InterruptedException,您可以决定下一步该做什么。