一、JUC相關概念
Java JUC(j.u.c)表示Java並發編程工具包,是Java SE 5.0提供的線程處理API中最重要的一個,它主要位於java.util.concurrent包中。JUC中包含了許多工具類,可以讓我們更加方便地進行多線程開發。下面我們來詳細介紹幾個與JUC相關的概念。
1.1 原子性
原子性指的是一個操作是不可分割的,也就是說在進行這個操作時,不存在其他的線程同時在進行同樣的操作。Java中提供了一些原子性的操作類,常見的有AtomicInteger、AtomicBoolean等,它們可以保證操作的原子性,從而避免了線程安全問題。
public class AtomicIntegerTest { private static AtomicInteger count = new AtomicInteger(); public static void main(String[] args) { ExecutorService executor = Executors.newFixedThreadPool(5); for (int i = 0; i { for (int j = 0; j < 10; j++) { System.out.println(count.incrementAndGet()); } }); } executor.shutdown(); } }
1.2 可見性
可見性指的是當一個線程對共享變數進行了修改後,其他線程能夠立即看到這個修改。Java中通過volatile關鍵字來實現可見性。
public class VolatileVariableTest { private static volatile boolean flag = false; public static void main(String[] args) throws InterruptedException { new Thread(() -> { while (!flag) {} System.out.println("Flag has been changed to true."); }).start(); Thread.sleep(1000); flag = true; System.out.println("Flag has been set to true."); } }
1.3 有序性
有序性指的是在並發情況下,程序的執行結果與理論預期的結果是一致的。Java中可以通過synchronized關鍵字或ReentrantLock類來實現有序性。
public class SynchronizedTest { private static int count = 0; public static synchronized void increase() { count++; } public static void main(String[] args) throws InterruptedException { ExecutorService executor = Executors.newFixedThreadPool(5); for (int i = 0; i { for (int j = 0; j < 10; j++) { increase(); } }); } executor.shutdown(); while (!executor.isTerminated()) {} System.out.println(count); } }
二、JUC的重要組件
Java JUC包含了很多重要的組件,這些組件可以讓我們更加方便地進行多線程開發。下面我們來介紹JUC中比較重要的幾個組件。
2.1 Semaphore
Semaphore是一個計數信號量,用於控制同時訪問某個資源的線程數量。例如,有一個任務需要保證最多只能有5個線程同時執行,那麼我們可以通過Semaphore來實現。
public class SemaphoreTest { private static Semaphore semaphore = new Semaphore(5); public static void main(String[] args) throws InterruptedException { ExecutorService executor = Executors.newCachedThreadPool(); for (int i = 0; i { try { semaphore.acquire(); System.out.println(Thread.currentThread().getName() + " is using the resource."); Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } finally { semaphore.release(); System.out.println(Thread.currentThread().getName() + " has released the resource."); } }); } executor.shutdown(); } }
2.2 CountDownLatch
CountDownLatch是一個同步工具類,它可以讓某個線程等待特定的一組操作完成後再繼續執行。例如,我們可以讓主線程等待10個子線程全部執行完畢後再繼續執行。
public class CountDownLatchTest { private static CountDownLatch latch = new CountDownLatch(10); public static void main(String[] args) throws InterruptedException { ExecutorService executor = Executors.newCachedThreadPool(); for (int i = 0; i { try { System.out.println(Thread.currentThread().getName() + " is executing."); Thread.sleep(500); latch.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } }); } latch.await(); System.out.println("All threads have finished executing."); executor.shutdown(); } }
2.3 CyclicBarrier
CyclicBarrier是另一個同步工具類,它可以讓一組線程互相等待,直到到達某個屏障點後再一起繼續執行。例如,我們可以讓10個線程分別執行不同的任務,然後在某個節點處等待,等待所有線程都到達之後再繼續執行。
public class CyclicBarrierTest { private static CyclicBarrier barrier = new CyclicBarrier(10); public static void main(String[] args) { ExecutorService executor = Executors.newCachedThreadPool(); for (int i = 0; i { try { System.out.println(Thread.currentThread().getName() + " is executing."); Thread.sleep(500); barrier.await(); System.out.println(Thread.currentThread().getName() + " continues executing."); } catch (InterruptedException | BrokenBarrierException e) { e.printStackTrace(); } }); } executor.shutdown(); } }
三、JUC中的線程安全容器
Java JUC包含了很多線程安全容器,它們可以讓我們在多線程環境下更加安全地進行元素的添加、刪除和讀取。下面我們來介紹JUC中比較重要的幾個線程安全容器。
3.1 ConcurrentHashMap
ConcurrentHashMap是一個支持高並發、線程安全的HashMap,它內部使用了分段鎖機制,可以保證並發訪問的安全性和效率。
public class ConcurrentHashMapTest { private static ConcurrentHashMap map = new ConcurrentHashMap(); public static void main(String[] args) throws InterruptedException { ExecutorService executor = Executors.newCachedThreadPool(); for (int i = 0; i { for (int j = 0; j < 10; j++) { map.put(UUID.randomUUID().toString(), j); } }); } executor.shutdown(); while (!executor.isTerminated()) {} System.out.println(map.size()); } }
3.2 CopyOnWriteArrayList
CopyOnWriteArrayList是一個支持高並發、線程安全的List,它內部使用了一種叫做「寫時複製」的機制,寫操作時會先複製出一個新的List進行操作,操作完成後再將原List指針指向新的List。因為讀操作不需要加鎖,所以它的讀操作速度比較快,但寫操作則比較慢。
public class CopyOnWriteArrayListTest { private static CopyOnWriteArrayList list = new CopyOnWriteArrayList(); public static void main(String[] args) throws InterruptedException { ExecutorService executor = Executors.newFixedThreadPool(5); for (int i = 0; i { for (int j = 0; j < 10; j++) { list.add(UUID.randomUUID().toString()); } }); } executor.shutdown(); while (!executor.isTerminated()) {} System.out.println(list.size()); } }
3.3 BlockingQueue
BlockingQueue是一個支持阻塞的隊列,在多線程環境下可以讓生產者線程和消費者線程更加安全地進行交互。BlockingQueue提供了一些常用的實現類,例如ArrayBlockingQueue、LinkedBlockingQueue等。
public class BlockingQueueTest { private static BlockingQueue queue = new LinkedBlockingQueue(); public static void main(String[] args) throws InterruptedException { ExecutorService executor = Executors.newCachedThreadPool(); executor.execute(() -> { try { for (int i = 0; i { try { while (true) { String element = queue.take(); System.out.println(element); } } catch (InterruptedException e) { e.printStackTrace(); } }); executor.shutdown(); } }
原創文章,作者:COSKA,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/349516.html