Java並行Condition介面


java.util.concurrent.locks.Condition介面提供一個執行緒掛起執行的能力,直到給定的條件為真。 Condition物件必須繫結到Lock,並使用newCondition()方法獲取物件。

Condition類的方法

以下是Condition類中可用的重要方法的列表。

序號 方法名稱 描述
1 public void await() 使當前執行緒等待,直到發出信號或中斷信號。
2 public boolean await(long time, TimeUnit unit) 使當前執行緒等待直到發出信號或中斷,或指定的等待時間過去。
3 public long awaitNanos(long nanosTimeout) 使當前執行緒等待直到發出信號或中斷,或指定的等待時間過去。
4 public long awaitUninterruptibly() 使當前執行緒等待直到發出信號。
5 public long awaitUntil() 使當前執行緒等待直到發出信號或中斷,或者指定的最後期限過去。
6 public void signal() 喚醒一個等待執行緒。
7 public void signalAll() 喚醒所有等待執行緒。

範例

以下TestThread程式演示了Condition介面的這些方法。這裡我們使用signal()通知和await()掛起執行緒。

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class TestThread {

   public static void main(String[] args) throws InterruptedException{
      ItemQueue itemQueue = new ItemQueue(10);

      //Create a producer and a consumer.
      Thread producer = new Producer(itemQueue);
      Thread consumer = new Consumer(itemQueue);

      //Start both threads.
      producer.start();
      consumer.start();

      //Wait for both threads to terminate.
      producer.join();
      consumer.join();
   }

   static class ItemQueue {

      private Object[] items = null;
      private int current = 0;
      private int placeIndex = 0;
      private int removeIndex = 0;

      private final Lock lock;
      private final Condition isEmpty;
      private final Condition isFull;

      public ItemQueue(int capacity) {
         this.items = new Object[capacity];
         lock = new ReentrantLock();
         isEmpty = lock.newCondition();
         isFull = lock.newCondition();
      }

      public void add(Object item) throws InterruptedException {
         lock.lock();
         while(current >= items.length)
            isFull.await();

         items[placeIndex] = item;

         placeIndex = (placeIndex + 1) % items.length;

         ++current;

         //Notify the consumer that there is data available.
         isEmpty.signal();

         lock.unlock();
      }

      public Object remove() throws InterruptedException {
         Object item = null;

         lock.lock();
         while(current <= 0){
            isEmpty.await();
         }
         item = items[removeIndex];

         removeIndex = (removeIndex + 1) % items.length;

         --current;

         //Notify the producer that there is space available.
         isFull.signal();
         lock.unlock();

         return item;
      }

      public boolean isEmpty(){
         return (items.length == 0);
      }
   }

   static class Producer extends Thread {

      private final ItemQueue queue;
      public Producer(ItemQueue queue) {
         this.queue = queue;
      }

      @Override
      public void run() {
         String[] numbers = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"};

         try {
            for(String number: numbers){
               queue.add(number);
               System.out.println("[Producer]: " + number);
            }
            queue.add(null);
         }
         catch (InterruptedException ex) {
            ex.printStackTrace();
         } 
      }
   }

   static class Consumer extends Thread {

      private final ItemQueue queue;
      public Consumer(ItemQueue queue) {
         this.queue = queue;
      }

      @Override
      public void run() {
         try {
            do {
               Object number = queue.remove();
               System.out.println("[Consumer]: " + number);
               if(number == null){
                  return;
               }
            } while(!queue.isEmpty());
         }
         catch (InterruptedException ex) {
            ex.printStackTrace();
         }
      }
   }
}

這將產生以下結果。

[Producer]: 1
[Consumer]: 1
[Producer]: 2
[Consumer]: 2
[Producer]: 3
[Consumer]: 3
[Producer]: 4
[Consumer]: 4
[Producer]: 5
[Producer]: 6
[Consumer]: 5
[Producer]: 7
[Consumer]: 6
[Consumer]: 7
[Producer]: 8
[Consumer]: 8
[Producer]: 9
[Consumer]: 9
[Producer]: 10
[Consumer]: 10
[Producer]: 11
[Consumer]: 11
[Producer]: 12
[Consumer]: 12
[Consumer]: null