睡眠时线程中断

时间:2016-03-28 08:27:30

标签: java multithreading

在下面的示例中,我试图优雅地终止两个线程。消费者线程在休眠时被中断,这应该将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();
            }
        }
    }

}

}

2 个答案:

答案 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)

javadocs

所示
  

如果在调用Object类的wait(),wait(long)或wait(long,int)方法,或者join(),join(long),join(long)时阻塞了这个线程,int),sleep(long)或sleep(long,int),这个类的方法,然后它的中断状态将被清除,它将收到InterruptedException。

因此,在您调用中断时消费者正在休眠状态,中断状态被清除,您收到InterruptedException,您可以决定下一步该做什么。