Runnable 和 Thread 用哪個好
使用Runnable接口的好處是:
- 避免了單繼承的限制:當你的類已經繼承了另一個類時,你仍然可以實現Runnable接口來創建線程。
- 提高代碼的復用性:你可以將Runnable對象傳遞給多個線程來執行,從而實現代碼的復用。
- 適合資源共享:多個線程可以共享同一個Runnable對象,從而實現對同一個資源的訪問。
使用Thread類的好處是:
- 簡單直觀:Thread類提供了一些常用的方法,如start()、sleep()等,可以更方便地控制線程的執行。
- 可以直接繼承Thread類來創建線程,不需要實現接口。
? ?如果你的類已經繼承了另一個類,或者需要與多個線程共享資源,那么使用Runnable接口是一個更好的選擇。如果你只需要簡單地創建一個線程并執行任務,可以直接繼承Thread類。
?notify 和 notifyAll 有什么區別
? ? ?在 Java 中,notify() 和 notifyAll() 都是 Object 類中的方法,用于喚醒等待在當前對象上的線程。區別在于:
- notify() 方法會喚醒在對象的等待池中等待時間最長的一個線程,該線程將進入可運行狀態,但并不能立即獲得鎖資源。如果有多個線程等待,則只有一個線程能被喚醒。
- notifyAll() 方法會喚醒所有在對象的等待池中等待的線程,所有線程都將進入可運行狀態,但并不能立即獲得鎖資源。
下面是一個例子,通過 synchronized、wait()、notify() 方法演示了 notify() 和 notifyAll() 的區別:
public class NotifyExample {public static void main(String[] args) {Message message = new Message();Thread thread1 = new Thread(new Waiter(message), "Waiter1");Thread thread2 = new Thread(new Waiter(message), "Waiter2");Thread thread3 = new Thread(new Notifier(message), "Notifier");thread1.start();thread2.start();thread3.start();try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}message.setReady(true);synchronized (message) {message.notify(); // 喚醒等待時間最長的一個線程}}
}class Message {private boolean ready;public boolean isReady() {return ready;}public void setReady(boolean ready) {this.ready = ready;}
}class Waiter implements Runnable {private final Message message;public Waiter(Message message) {this.message = message;}@Overridepublic void run() {synchronized (message) {try {if (!message.isReady()) {System.out.println(Thread.currentThread().getName() + ": 正在等待消息...");message.wait();}} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + ": 收到消息!");}}
}class Notifier implements Runnable {private final Message message;public Notifier(Message message) {this.message = message;}@Overridepublic void run() {synchronized (message) {System.out.println(Thread.currentThread().getName() + ": 準備通知等待的線程");message.setReady(true);
// message.notify(); // 使用 notify() 方法message.notifyAll(); // 使用 notifyAll() 方法}}
}
運行上述代碼,結果會根據調用的 notify() 或 notifyAll() 方法而有所不同。如果使用 notify() 方法,則只有一個 Waiter 線程會被喚醒并繼續執行;如果使用 notifyAll() 方法,則所有的 Waiter 線程都會被喚醒并繼續執行。
總結
? ??在Java中,notify()和notifyAll()是用于線程間通信的方法。
-
notify()方法:該方法用于喚醒在對象的等待池中等待的單個線程。如果有多個線程在等待,則隨機選擇一個線程被喚醒。被喚醒的線程將進入就緒狀態,等待獲取對象的鎖。
-
notifyAll()方法:該方法用于喚醒在對象的等待池中等待的所有線程。被喚醒的線程將進入就緒狀態,等待獲取對象的鎖。notifyAll()相當于廣播通知,通知所有等待的線程。
-
Runnable接口:Runnable是一個函數式接口,用于定義一個可以被線程執行的任務。實現Runnable接口的類可以被傳遞給Thread類的構造方法,從而創建一個線程。Runnable接口只有一個run()方法,需要在該方法中定義線程的執行邏輯。
-
Thread類:Thread類是Java中表示線程的類,可以通過繼承Thread類或傳遞實現Runnable接口的對象來創建線程。Thread類提供了一些方法用于管理線程,如start()用于啟動線程,sleep()用于使線程休眠,join()用于等待其他線程執行完畢等。
- notify()和notifyAll()方法用于線程間通信,喚醒等待的線程。
- Runnable接口用于定義一個可以被線程執行的任務。
- Thread類是Java中表示線程的類,可以通過繼承Thread類或傳遞實現Runnable接口的對象來創建線程。