Java Concurrency - Condition Interface
อินเทอร์เฟซ java.util.concurrent.locks.Condition จัดเตรียมความสามารถของเธรดเพื่อระงับการดำเนินการจนกว่าเงื่อนไขที่กำหนดจะเป็นจริง อ็อบเจ็กต์ Condition จำเป็นต้องถูกผูกไว้กับ Lock และรับได้โดยใช้เมธอด newCondition ()
เงื่อนไขวิธีการ
ต่อไปนี้เป็นรายการวิธีการสำคัญที่มีอยู่ในคลาส 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 ที่นี่เราใช้สัญญาณ () เพื่อแจ้งเตือนและรอ () เพื่อระงับเธรด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) {
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
[Producer]: 2
[Producer]: 3
[Producer]: 4
[Producer]: 5
[Producer]: 6
[Producer]: 7
[Producer]: 8
[Producer]: 9
[Producer]: 10
[Producer]: 11
[Producer]: 12
[Consumer]: null