全球觀焦點(diǎn):java線程的創(chuàng)建和管理(二)
四、線程同步與互斥
Java 中的線程同步和互斥機(jī)制可以防止多個線程同時訪問共享資源導(dǎo)致數(shù)據(jù)不一致的問題。Java 中的線程同步和互斥機(jī)制有多種實(shí)現(xiàn)方式,包括 synchronized 關(guān)鍵字、Lock 接口、Semaphore 類、Condition 接口等。
synchronized 關(guān)鍵字
synchronized 關(guān)鍵字可以保證同步訪問共享資源,其用法有兩種:
修飾實(shí)例方法在方法前加上 synchronized 關(guān)鍵字,保證同一時刻只有一個線程能夠執(zhí)行該方法。
【資料圖】
public synchronized void method() { // 同步代碼塊}
修飾代碼塊在代碼塊前加上 synchronized 關(guān)鍵字,保證同一時刻只有一個線程能夠執(zhí)行該代碼塊。
public void method() { synchronized (this) { // 同步代碼塊 }}
Lock 接口
Lock 接口提供了比 synchronized 更為靈活的鎖機(jī)制。Lock 接口有多個實(shí)現(xiàn)類,其中最常用的是 ReentrantLock 類。ReentrantLock 類實(shí)現(xiàn)了 Lock 接口,使用方式如下:
import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class MyRunnable implements Runnable { private Lock lock = new ReentrantLock(); // 創(chuàng)建可重入鎖 @Override public void run() { lock.lock(); // 獲取鎖 try { // 同步代碼塊 } finally { lock.unlock(); // 釋放鎖 } }}
在該例子中,我們使用 ReentrantLock 類創(chuàng)建了一個可重入鎖,并在 run() 方法中使用了 lock() 方法獲取鎖,使用了 unlock() 方法釋放鎖。
Semaphore 類
Semaphore 類可以控制并發(fā)線程的數(shù)量,其用法如下:
import java.util.concurrent.Semaphore;public class MyRunnable implements Runnable { private Semaphore semaphore = new Semaphore(2); // 創(chuàng)建 Semaphore 對象,限制線程數(shù)量為 2 @Override public void run() { try { semaphore.acquire(); // 獲取許可證 // 同步代碼塊 } catch (InterruptedException e) { e.printStackTrace(); } finally { semaphore.release(); // 釋放許可證 } }}
在該例子中,我們創(chuàng)建了一個 Semaphore 對象,限制線程數(shù)量為 2,然后在 run() 方法中使用了 acquire() 方法獲取許可證,使用了 release() 方法釋放許可證。
Condition 接口
Condition 接口可以實(shí)現(xiàn)線程之間的通信,其用法如下:
import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class MyRunnable implements Runnable { private Lock lock = new ReentrantLock(); private Condition condition = lock.newCondition(); // 創(chuàng)建條件變量 @Override public void run() { lock.lock(); try { while (true) { condition.await(); // 等待信號 // 處理信號 } } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } public void signal() { lock.lock(); try { condition.signal(); // 發(fā)送信號 } finally { lock.unlock(); } }}
在該例子中,我們使用 Lock 和 Condition 接口實(shí)現(xiàn)了線程之間的通信。在 run() 方法中,我們使用了 await() 方法等待信號,使用了 signal() 方法發(fā)送信號。
五、線程池
線程池是一種重用線程的機(jī)制,可以避免線程的頻繁創(chuàng)建和銷毀,提高了線程的利用率。Java 中的線程池是通過 Executor 框架實(shí)現(xiàn)的,包括 Executor、ExecutorService 和 ThreadPoolExecutor 三個類。
Executor
Executor 是一個接口,只定義了一個 execute(Runnable command) 方法,用于執(zhí)行 Runnable 對象。
import java.util.concurrent.Executor;public class MyRunnable implements Runnable { @Override public void run() { // 線程執(zhí)行的代碼 }}public class Test { public static void main(String[] args) { Executor executor = Executors.newSingleThreadExecutor(); // 創(chuàng)建 Executor 對象 executor.execute(new MyRunnable()); // 執(zhí)行線程 }}
在該例子中,我們使用 Executors 工廠類創(chuàng)建了一個單線程的 Executor 對象,然后使用 execute() 方法執(zhí)行了一個 MyRunnable 對象。
ExecutorService
ExecutorService 接口繼承自 Executor 接口,提供了更多的方法,如提交任務(wù)、關(guān)閉線程池等。
import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class MyRunnable implements Runnable { @Override public void run() { // 線程執(zhí)行的代碼 }}public class Test { public static void main(String[] args) { ExecutorService executorService = Executors.newFixedThreadPool(2); // 創(chuàng)建 ExecutorService 對象 executorService.execute(new MyRunnable()); // 執(zhí)行線程 executorService.shutdown(); // 關(guān)閉線程池 }}
在該例子中,我們使用 Executors 工廠類創(chuàng)建了一個固定大小為 2 的線程池,然后使用 execute() 方法執(zhí)行了一個 MyRunnable 對象,最后使用 shutdown() 方法關(guān)閉了線程池。
ThreadPoolExecutor
ThreadPoolExecutor 類是 ExecutorService 接口的默認(rèn)實(shí)現(xiàn),提供了更為靈活的線程池管理。
import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;public class MyRunnable implements Runnable { @Override public void run() { // 線程執(zhí)行的代碼 }}public class Test { public static void main(String[] args) { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 4, 60, TimeUnit.SECONDS, new LinkedBlockingQueue()); // 創(chuàng)建 ThreadPoolExecutor 對象 threadPoolExecutor.execute(new MyRunnable()); // 執(zhí)行線程 threadPoolExecutor.shutdown(); // 關(guān)閉線程池 }}
在該例子中,我們使用 ThreadPoolExecutor 類創(chuàng)建了一個大小為 2-4 的線程池,使用 execute() 方法執(zhí)行了一個 MyRunnable 對象,最后使用 shutdown() 方法關(guān)閉了線程池。
關(guān)鍵詞: