Java中的執行緒通訊詳解
大家好,我是微賺淘客系統3.0的小編,是個冬天不穿秋褲,天冷也要風度的程式猿!
在多執行緒程式設計中,執行緒之間的通訊是一個重要且複雜的主題。為了確保多執行緒程式的正確性和效率,執行緒需要能夠互相通訊並協調工作。Java 提供了多種方式來實現執行緒間的通訊,如 wait()
、notify()
、notifyAll()
方法,以及更高階的併發工具類。本文將詳細介紹 Java 中的執行緒通訊,涵蓋基本概念、常用方法和具體程式碼示例。
一、基本概念
執行緒通訊是指執行緒之間透過某種機制傳遞資訊,以協調它們之間的行為。Java 中提供了內建的執行緒通訊機制,包括 wait()
、notify()
和 notifyAll()
方法,這些方法都是 Object
類的一部分,每個物件都可以作為執行緒通訊的鎖。
二、wait()
、notify()
和notifyAll()
方法
wait()
方法
wait()
方法使當前執行緒進入等待狀態,直到其他執行緒呼叫 notify()
或 notifyAll()
方法喚醒它。該方法必須在同步塊或同步方法中呼叫,否則會丟擲 IllegalMonitorStateException
異常。
notify()
方法
notify()
方法喚醒一個正在等待該物件監視器的執行緒。如果有多個執行緒在等待,則選擇其中一個執行緒喚醒。被喚醒的執行緒在獲取物件的監視器後,才能繼續執行。
notifyAll()
方法
notifyAll()
方法喚醒所有正在等待該物件監視器的執行緒。被喚醒的執行緒在獲取物件的監視器後,才能繼續執行。
三、程式碼示例
以下示例演示瞭如何使用 wait()
、notify()
和 notifyAll()
方法進行執行緒通訊。
1. 生產者-消費者模型
package cn.juwatech.threads;
import java.util.LinkedList;
import java.util.Queue;
public class ProducerConsumerExample {
private static final int CAPACITY = 5;
private final Queue<Integer> queue = new LinkedList<>();
private final Object lock = new Object();
public static void main(String[] args) {
ProducerConsumerExample example = new ProducerConsumerExample();
Thread producerThread = new Thread(example.new Producer());
Thread consumerThread = new Thread(example.new Consumer());
producerThread.start();
consumerThread.start();
}
class Producer implements Runnable {
@Override
public void run() {
int value = 0;
while (true) {
synchronized (lock) {
while (queue.size() == CAPACITY) {
try {
lock.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
queue.offer(value);
System.out.println("Produced: " + value);
value++;
lock.notify();
}
}
}
}
class Consumer implements Runnable {
@Override
public void run() {
while (true) {
synchronized (lock) {
while (queue.isEmpty()) {
try {
lock.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
int value = queue.poll();
System.out.println("Consumed: " + value);
lock.notify();
}
}
}
}
}
在這個示例中,生產者執行緒生成整數並將其放入佇列中,而消費者執行緒從佇列中取出整數並進行消費。wait()
和 notify()
方法用於協調生產者和消費者之間的工作。
四、使用更高階的併發工具類
Java 提供了更高階的併發工具類,如 BlockingQueue
、Semaphore
、CountDownLatch
和 CyclicBarrier
,它們簡化了執行緒間的通訊和同步。
1. 使用 BlockingQueue
實現生產者-消費者模型
package cn.juwatech.threads;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class BlockingQueueExample {
private static final int CAPACITY = 5;
private final BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(CAPACITY);
public static void main(String[] args) {
BlockingQueueExample example = new BlockingQueueExample();
Thread producerThread = new Thread(example.new Producer());
Thread consumerThread = new Thread(example.new Consumer());
producerThread.start();
consumerThread.start();
}
class Producer implements Runnable {
@Override
public void run() {
int value = 0;
while (true) {
try {
queue.put(value);
System.out.println("Produced: " + value);
value++;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
class Consumer implements Runnable {
@Override
public void run() {
while (true) {
try {
int value = queue.take();
System.out.println("Consumed: " + value);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
}
在這個示例中,BlockingQueue
處理了同步和通訊邏輯,使得程式碼更加簡潔和易於理解。
2. 使用 Semaphore
控制執行緒訪問
Semaphore
是一種計數訊號量,用於控制同時訪問特定資源的執行緒數量。
package cn.juwatech.threads;
import java.util.concurrent.Semaphore;
public class SemaphoreExample {
private static final int PERMITS = 3;
private final Semaphore semaphore = new Semaphore(PERMITS);
public static void main(String[] args) {
SemaphoreExample example = new SemaphoreExample();
for (int i = 0; i < 10; i++) {
new Thread(example.new Worker(i)).start();
}
}
class Worker implements Runnable {
private final int workerId;
Worker(int workerId) {
this.workerId = workerId;
}
@Override
public void run() {
try {
semaphore.acquire();
System.out.println("Worker " + workerId + " is working...");
Thread.sleep(2000);
System.out.println("Worker " + workerId + " finished working.");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
semaphore.release();
}
}
}
}
在這個示例中,Semaphore
控制同時最多隻有三個執行緒可以訪問資源,其餘執行緒必須等待。
五、執行緒通訊的最佳實踐
- 避免忙等待:使用
wait()
、notify()
、notifyAll()
或併發工具類避免忙等待,提高效率。 - 適當使用鎖和同步:確保共享資源的安全訪問,避免死鎖。
- 選擇合適的併發工具類:根據具體需求選擇合適的併發工具類,簡化執行緒通訊和同步邏輯。
透過以上內容,我們詳細介紹了 Java 中的執行緒通訊機制,包括基本概念、常用方法及其具體程式碼示例,並探討了使用更高階的併發工具類實現執行緒通訊的方法。掌握這些知識,能夠幫助我們編寫出更加高效和可靠的多執行緒程式。
著作權歸聚娃科技微賺淘客系統開發者團隊,轉載請註明出處!