Java中的wait方法是一個非常重要的多線程技術,它可以使線程處於等待狀態,直到其他線程調用notify或notifyAll方法喚醒它。wait和notify方法通常用於協調線程之間的操作,以確保多個線程可以正確共享資源。下面從多個方面來詳細闡述Java中的wait方法。
一、wait和notify方法的概述
每個Java對象都有一個監視器(monitor),它是用來控制對該對象的訪問的。一個線程要想進入某個對象的監視器區域,必須先獲得該對象的鎖。然後可以通過wait方法來釋放該對象的鎖並進入等待狀態,直到其他線程調用notify或notifyAll方法喚醒它。notify方法會選擇一個等待該對象的線程進行喚醒,而notifyAll方法會喚醒所有等待該對象的線程。
public synchronized void wait() throws InterruptedException public final native void notify() public final native void notifyAll()
wait和notify方法只能在同步方法或同步塊中使用。如果一個線程在調用wait方法前沒有獲得該對象的鎖,會拋出IllegalMonitorStateException異常。
二、wait方法的阻塞和喚醒
調用wait方法會釋放該對象的鎖並將線程置於等待狀態,此時線程處於阻塞狀態,並且不佔用CPU資源。如果其他線程獲得了該對象的鎖並調用notify或notifyAll方法,則該線程將被喚醒並嘗試重新獲取該對象的鎖。
下面是一個使用wait和notify方法實現的線程間通信的示例:
class Monitor { public synchronized void print() { for(int i=0; i { monitor.print(); }); // 啟動打印線程 printer.start(); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } // 創建另一個線程喚醒打印線程 Thread resumer = new Thread(() -> { monitor.resume(); }); // 啟動喚醒線程 resumer.start(); } }
在這個示例中,Monitor類中的print方法調用了wait方法來釋放鎖並等待喚醒。resume方法則調用了notify方法來喚醒等待該對象的線程。程序中創建了兩個線程:一個打印線程和一個喚醒線程,喚醒線程會在打印線程執行到第二次循環時調用resume方法喚醒打印線程。
三、wait方法與notify方法的應用
1、wait方法和notify方法在線程間通信中的應用
wait方法和notify方法通常用於協調多個線程之間的操作,以確保多個線程可以正確共享資源。在多個線程間共享一個對象的情況下,某個線程在獲取該對象的鎖後可能需要等待其他線程的操作完成,才能進行接下來的操作。這時,該線程可以調用wait方法釋放鎖並等待喚醒。其他線程完成操作後,可以調用notify方法來喚醒等待該對象的線程。
2、wait方法和notify方法在線程池中的應用場景
Java中的線程池是一個線程管理機制,它可以在任務到達時分配一個可用的線程進行處理,而不需要創建新的線程。線程池中的每個線程都會佔用一些資源,因此需要根據實際的需求來控制線程的數量。
如果線程池中的所有線程都在處理任務,而沒有可用的線程來處理新的任務時,可以使用wait和notify方法來實現線程池的阻塞和喚醒。當線程池中沒有可用的線程時,調用線程可以調用wait方法釋放鎖並等待喚醒。當有線程處理完任務後,可以調用notify方法來喚醒等待線程。
下面是一個使用wait和notify方法實現線程池的示例:
class ThreadPool { private int nThreads; private List<Runnable> tasks; private List<WorkerThread> workers; public ThreadPool(int nThreads) { this.nThreads = nThreads; this.tasks = new LinkedList<>(); this.workers = new ArrayList<>(); for(int i=0; i<nThreads; i++) { WorkerThread worker = new WorkerThread(); workers.add(worker); worker.start(); } } public synchronized void execute(Runnable task) { tasks.add(task); notify(); } public synchronized void shutDown() { tasks.clear(); workers.forEach(worker -> worker.shutdown()); notifyAll(); } private class WorkerThread extends Thread { private boolean running = true; @Override public void run() { while(running) { Runnable task = null; synchronized (ThreadPool.this) { while(tasks.isEmpty()) { try { // 等待喚醒 ThreadPool.this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } task = tasks.remove(0); } if(task != null) { task.run(); } } } public void shutdown() { running = false; } } } public class ThreadPoolExample { public static void main(String[] args) { // 創建一個線程池 ThreadPool threadPool = new ThreadPool(10); // 啟動若干個任務 for(int i=0; i<100; i++) { final int index = i; threadPool.execute(() -> System.out.println("Task " + index + " is running.")); } // 加入任務隊列之後,等待1s停止線程池 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } threadPool.shutDown(); } }
在這個示例中,ThreadPool類使用wait和notify方法來實現線程池的阻塞和喚醒。execute方法負責將任務添加到任務隊列中,並喚醒等待線程。WorkerThread類負責從任務隊列中取出任務並執行,如果任務隊列為空,則進入等待狀態。shutDown方法負責清空任務隊列並停止所有的線程。
總結
本文從多個方面對Java中的wait方法進行了詳細闡述,包括wait和notify方法的概述、wait方法的阻塞和喚醒、wait方法和notify方法在線程間通信中的應用、wait方法和notify方法在線程池中的應用場景等。wait方法是Java多線程技術中非常重要的一個方法,對於理解多線程編程、掌握線程間通信以及設計線程安全的程序等方面都具有重要的參考價值。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/247615.html