接着上一篇文章今天我们来介绍下LockSupport和Java中线程的中断(interrupt)。
其实除了LockSupport,Java之初就有Object对象的wait和notify方法可以实现线程的阻塞和唤醒。那么它们的区别 是什么呢?
主要的区别应该说是它们面向的对象不同。阻塞和唤醒是对于线程来说的,LockSupport的park/unpark更符合这个语义,以“线程”作为方法的参数, 语义更清晰,使用起来也更方便。而wait/notify的实现使得“线程”的阻塞/唤醒对线程本身来说是被动的,要准确的控制哪个线程、什么时候阻塞/唤醒很困难, 要不随机唤醒一个线程(notify)要不唤醒所有的(notifyAll)。
wait/notify最典型的例子应该就是生产者/消费者了:
class BoundedBuffer1 { private int contents; final Object[] items = new Object[100]; int putptr, takeptr, count; public synchronized void put(Object x) { while (count == items.length) { try { wait(); } catch (InterruptedException e) { } } items[putptr] = x; if (++putptr == items.length) putptr = 0; ++count; notifyAll(); } public synchronized Object take() { while (count == 0) { try { wait(); } catch (InterruptedException e) { } } Object x = items[takeptr]; if (++takeptr == items.length) takeptr = 0; --count; notifyAll(); return x; } public static class Producer implements Runnable { private BoundedBuffer1 q; Producer(BoundedBuffer1 q) { this.q = q; new Thread(this, "Producer").start(); } int i = 0; public void run() { int i = 0; while (true) { q.put(i++); } } } public static class Consumer implements Runnable { private BoundedBuffer1 q; Consumer(BoundedBuffer1 q) { this.q = q; new Thread(this, "Consumer").start(); } public void run() { while (true) { System.out.println(q.take()); } } } public static void main(String[] args) throws InterruptedException { final BoundedBuffer1 buffer = new BoundedBuffer1(); new Thread(new Producer(buffer)).start(); new Thread(new Consumer(buffer)).start(); } }
