Lock版的生产者消费者问题
那么在synchronized中呢,我们是使用wait和notify来控制线程的。
public synchronized void increment() throws InterruptedException { while (number != 0) { // 等待 this.wait(); } Thread.sleep(100); number++; // 业务 System.out.println(Thread.currentThread().getName() + " => " + number); // 通知其它线程我+1加完了 this.notifyAll(); }
用了Lock之后、会有一些细微的改变,wait->condition.await, notify->condition.signal
class doSomething { private int number = 0; Lock lock = new ReentrantLock(); Condition condition = lock.newCondition(); // +1 public void increse() throws InterruptedException { lock.lock(); try { while (number != 0) { condition.await(); } Thread.sleep(100); number++; System.out.println(Thread.currentThread().getName() + "->" + number); condition.signalAll(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } // -1 public void decrese() throws InterruptedException { lock.lock(); try { while (number == 0) { condition.await(); } Thread.sleep(100); number--; System.out.println(Thread.currentThread().getName() + "->" + number); condition.signalAll(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } }
思考:既然有了wait和notify、那为什么我们还要多此一举来使用condition的等待和唤醒呢?
这是因为condition能够做到有序,精准的通知和唤醒线程
那么如何做到有序精准的来唤醒线程呢?
public class C { public static void main(String[] args) { doSomething2 doSomething2 = new doSomething2(); new Thread(() -> { for (int i = 0; i < 10; i++) { doSomething2.printA(); } }, "A").start(); new Thread(() -> { for (int i = 0; i < 10; i++) { doSomething2.printB(); } }, "B").start(); new Thread(() -> { for (int i = 0; i < 10; i++) { doSomething2.printC(); } }, "C").start(); } } @SuppressWarnings("all") class doSomething2 { private int number = 1; Lock lock = new ReentrantLock(); private Condition condition1 = lock.newCondition(); private Condition condition2 = lock.newCondition(); private Condition condition3 = lock.newCondition(); public void printA() { lock.lock(); try { while (number != 1) { // 等待 condition1.await(); } Thread.sleep(100); System.out.println(Thread.currentThread().getName() + "AAA"); // 唤醒 condition2.signal(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } public void printB() { lock.lock(); try { while (number != 1) { // 等待 condition2.await(); } Thread.sleep(100); System.out.println(Thread.currentThread().getName() + "BBB"); // 唤醒 condition3.signal(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } public void printC() { lock.lock(); try { while (number != 1) { // 等待 condition3.await(); } Thread.sleep(100); System.out.println(Thread.currentThread().getName() + "CCC"); // 唤醒 condition1.signal(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } }