一、什麼是線程
線程是操作系統進行任務調度的最小單位。在Java中,線程是一種輕量級的進程,擁有自己的執行路徑,可以與其他線程共享進程中的資源。
Java中的線程分為兩類:用戶線程和守護線程。其中,用戶線程是進程中的主線程,當所有用戶線程結束時,進程才會結束。守護線程則是為其他線程提供服務,當所有用戶線程結束時,守護線程也會隨之結束。
二、如何創建線程
Java中有兩種方式可以創建線程:
1. 繼承Thread類
public class MyThread extends Thread { public void run() { // 線程執行邏輯 } } // 創建線程並啟動 MyThread t = new MyThread(); t.start();
2. 實現Runnable介面
public class MyRunnable implements Runnable { public void run() { // 線程執行邏輯 } } // 創建線程並啟動 Thread t = new Thread(new MyRunnable()); t.start();
三、線程的狀態
Java中的線程有6種狀態:
1. 新建狀態(New)
當創建線程對象時,線程處於新建狀態。
2. 就緒狀態(Runnable)
當線程被創建後,它將進入就緒狀態,等待系統調度執行。
3. 運行狀態(Running)
當線程獲得CPU時間片後,它進入運行狀態,在此狀態下線程執行具體的任務。
4. 阻塞狀態(Blocked)
當線程由於某些原因無法獲得所需的資源時,它將進入阻塞狀態,直到資源被釋放。
5. 等待狀態(Waiting)
當線程調用wait()方法等待某個條件滿足時,它將進入等待狀態,直到被喚醒。
6. 終止狀態(Terminated)
當線程執行完畢或遇到異常時,它將進入終止狀態。
四、線程同步
線程同步是指多個線程在訪問共享資源時,通過互斥機制協調彼此之間的關係,以避免數據不一致或其他並發問題。
1. synchronized關鍵字
synchronized關鍵字是Java提供的最基本的線程同步機制,它可以用於修飾方法或代碼塊。使用synchronized關鍵字修飾後,同步對象(也稱鎖對象)將會成為區分線程的標誌。
public synchronized void method() { // 有且僅有一條線程訪問此方法 } public void method() { synchronized (this) { // 有且僅有一條線程訪問此代碼塊 } }
2. Lock介面
Lock介面也是一種線程同步機制,它提供了更加靈活和強大的同步方式。與synchronized關鍵字相比,Lock介面可以實現多個線程同時訪問同一資源,通過tryLock方法可以避免死鎖等問題。
Lock lock = new ReentrantLock(); public void method() { lock.lock(); try { // 獲得鎖,執行線程同步代碼 } finally { lock.unlock(); } }
五、線程池
線程池是一種預先創建好的線程集合,在任務到來時,從集合中取出一個線程來處理任務,可以避免頻繁創建和銷毀線程,從而提升代碼執行效率。
1. Executors類
Java提供了Executors工廠類,可以快速創建常用的線程池。Executors提供的線程池有以下幾種:
a. newFixedThreadPool
創建一個固定大小的線程池,池中的線程數量始終不變。
ExecutorService executor = Executors.newFixedThreadPool(10); executor.submit(new MyTask());
b. newCachedThreadPool
創建一個大小不受限制的線程池,池中線程數量可根據任務數量自動調整。
ExecutorService executor = Executors.newCachedThreadPool(); executor.submit(new MyTask());
c. newSingleThreadExecutor
創建一個單線程的線程池,它保證所有任務按順序執行。
ExecutorService executor = Executors.newSingleThreadExecutor(); executor.submit(new MyTask());
2. ThreadPoolExecutor類
除了Executors工廠類提供的線程池之外,還可以通過ThreadPoolExecutor類自定義線程池。ThreadPoolExecutor提供了非常靈活的線程池配置項,包括核心線程數、最大線程數、線程存活時間、拒絕策略等。
ThreadPoolExecutor executor = new ThreadPoolExecutor( 2, 5, 60, TimeUnit.SECONDS, new LinkedBlockingDeque(), new ThreadPoolExecutor.AbortPolicy() ); executor.execute(new MyTask());
六、線程通信
線程通信是指多個線程之間通過共享變數進行數據傳遞和同步的過程。
1. wait()和notify()方法
wait()方法用於等待某個條件的發生,會使當前線程釋放佔有的鎖,並進入等待隊列中等待被喚醒。notify()方法用於喚醒等待在等待隊列中的一個線程。
public synchronized void producer() throws InterruptedException { while (count == BUFFER_SIZE) { // 緩衝區已滿,等待消費者消費 wait(); } // 生產數據 buffer[in] = data; in = (in + 1) % BUFFER_SIZE; count++; // 喚醒等待在等待隊列中的消費者 notify(); } public synchronized void consumer() throws InterruptedException { while (count == 0) { // 緩衝區為空,等待生產者生產 wait(); } // 消費數據 data = buffer[out]; out = (out + 1) % BUFFER_SIZE; count--; // 喚醒等待在等待隊列中的生產者 notify(); }
2. Condition介面
Condition介面是Java提供的高級線程同步機制,它可以讓線程在等待某個條件滿足時進入等待狀態,而不是一直佔用CPU資源。
Lock lock = new ReentrantLock(); Condition condition = lock.newCondition(); public void method() throws InterruptedException { lock.lock(); try { while (condition不滿足) { condition.await(); } // 線程執行邏輯 } finally { lock.unlock(); } } public void changeCondition() { lock.lock(); try { // 改變condition的值 condition.signalAll(); } finally { lock.unlock(); } }
七、總結
Java線程編程是Java開發中必不可少的一部分,在並發編程中,線程的創建、狀態、同步、池和通信等方面都需要掌握。對於初學者來說,建議從基礎入手,逐漸提高對多線程編程的理解和實戰經驗。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/297953.html