Semaphore
特性
Semaphore
是 Java 中的一個同步工具,用於控制同時訪問某個特定資源的執行緒數量。
使用時可以先new 出並設定初始可被使用的憑證數
1
| Semaphore semaphore = new Semaphore(3);
|
可以透過以下使用憑證
使用完後可以透過以下釋放資源
如果拿不到資源的話就會一直處於等待狀態,所以在使用完畢後務必釋放資源
範例
生產者與消費者拿取同一buffer
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
| package thread.consumer;
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore;
public class Main { static int[] buffer = new int[3]; static int producerIndex = 0; static int consumerIndex = 0; static Semaphore s_lock, n_lock, e_lock;
private static void append(int i) { buffer[producerIndex] = i; if (producerIndex != buffer.length - 1) { producerIndex++; } else { producerIndex = 0; } }
private static int take() { int temp = buffer[consumerIndex]; if (consumerIndex != buffer.length - 1) { consumerIndex++; } else { consumerIndex = 0; } return temp; }
private static class ProducerTask implements Runnable { int thread_id;
public ProducerTask(int thread_id) { this.thread_id = thread_id; System.out.println("Producer #" + thread_id + " launched. "); }
@Override public void run() { try { for (int i = 0; i < 20; i++) { e_lock.acquire(); s_lock.acquire(); int randomInt = (int) (Math.random() * 10); System.out.println("Producer #" + thread_id + " produced " + randomInt); append(randomInt); s_lock.release(); n_lock.release(); } } catch (InterruptedException e) { e.printStackTrace(); } } }
private static class ConsumerTask implements Runnable { int thread_id;
public ConsumerTask(int thread_id) { this.thread_id = thread_id; System.out.println("Consumer #" + thread_id + " launched. "); }
@Override public void run() { try { int value_took; for (int i = 0; i < 20; i++) { n_lock.acquire(); s_lock.acquire(); value_took = take(); System.out.println("Consumer #" + thread_id + " consumed " + value_took); s_lock.release(); e_lock.release(); } } catch (InterruptedException e) { e.printStackTrace(); } } }
public static void main(String[] args) { System.out.println("Using " + 4 + "threads. "); s_lock = new Semaphore(1); n_lock = new Semaphore(0); e_lock = new Semaphore(buffer.length);
ExecutorService executorService = Executors.newFixedThreadPool(4); for (int i = 0; i < 4; i++) { if (i % 2 == 0) { executorService.execute(new ProducerTask(i)); } else { executorService.execute(new ConsumerTask(i)); } } executorService.shutdown(); } }
|