多線程是 Java 並發編程的基石。本文通過一個生動的「選擇旅遊城市」案例,對比演示繼承 Thread 類與實現 Runnable 接口兩種創建線程的寫法,並展示 sleep()、Random、getName() 等核心 API 的使用。
public class Ly_Thread extends Thread {
@Override
public void run() {
Random r = new Random();
for (int i = 1; i <= 10; i++) {
try {
int sleepMs = r.nextInt(1000); // 0-999ms
Thread.sleep(sleepMs);
System.out.print(sleepMs + "毫秒,去");
System.out.println(this.getName()); // 獲取線程名
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Ly_Thread t1 = new Ly_Thread();
t1.setName("重慶");
t1.start(); // 啟動線程,調用 run()
Ly_Thread t2 = new Ly_Thread();
t2.setName("上海");
t2.start();
}
}
public class CityRunner implements Runnable {
private String cityName;
public CityRunner(String cityName) {
this.cityName = cityName;
}
@Override
public void run() {
Random r = new Random();
for (int i = 1; i <= 10; i++) {
try {
int sleepMs = r.nextInt(1000);
Thread.sleep(sleepMs);
System.out.print(sleepMs + "毫秒,去");
System.out.println(cityName + " [線程:" + Thread.currentThread().getName() + "]");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Thread t1 = new Thread(new CityRunner("重慶"), "Thread-重慶");
Thread t2 = new Thread(new CityRunner("上海"), "Thread-上海");
t1.start();
t2.start();
}
}

345毫秒,去重慶 12毫秒,去上海 789毫秒,去重慶 ... 0毫秒,去上海 <-- 上海先跑完 10 次 決定去上海旅遊!
| 對比項 | 繼承 Thread | 實現 Runnable |
|---|---|---|
| 實現方式 | class MyThread extends Thread | class MyTask implements Runnable |
| 啟動方式 | new MyThread().start() | new Thread(new MyTask()).start() |
| 獲取名稱 | this.getName() | Thread.currentThread().getName() |
| 優勢 | 代碼簡潔,直接訪問 Thread 方法 | 避免單繼承限制,任務與線程分離,支持線程池、Lambda |
| 推薦場景 | 簡單測試、教學演示 | 生產環境、複雜業務、線程池提交 |
當前案例僅打印日志,無「裁判」邏輯。實際開發中可引入 CountDownLatch、AtomicBoolean 或共享標誌位,在 run() 結束時檢查並設置「勝利者」,實現真正的「先到先得」業務邏輯。