Java 多執行緒 (Multithreading)

多執行緒讓程式可以同時執行多個任務,提高效能和回應性。

建立執行緒

方式一:繼承 Thread

public class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("執行緒執行中:" + getName());
    }
}

// 使用
MyThread thread = new MyThread();
thread.start();  // 啟動執行緒

方式二:實作 Runnable(推薦)

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("執行緒執行中");
    }
}

// 使用
Thread thread = new Thread(new MyRunnable());
thread.start();

// Lambda 寫法
Thread thread2 = new Thread(() -> {
    System.out.println("Lambda 執行緒");
});
thread2.start();

方式三:Callable(有回傳值)

import java.util.concurrent.*;

Callable<Integer> task = () -> {
    return 42;
};

ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Integer> future = executor.submit(task);

Integer result = future.get();  // 取得結果(會等待)
System.out.println(result);     // 42

executor.shutdown();

執行緒方法

Thread thread = new Thread(() -> {
    System.out.println("執行中...");
});

thread.start();              // 啟動執行緒
thread.join();               // 等待執行緒結束
thread.join(1000);           // 最多等待 1 秒
Thread.sleep(1000);          // 休眠 1 秒
thread.interrupt();          // 中斷執行緒
thread.isAlive();            // 是否執行中
thread.getName();            // 取得名稱
thread.setName("MyThread");  // 設定名稱
thread.setPriority(5);       // 設定優先權(1-10)

Thread.currentThread();      // 取得目前執行緒

更多說明請參考 Java 執行緒生命週期

同步 (Synchronization)

synchronized 方法

public class Counter {
    private int count = 0;
    
    public synchronized void increment() {
        count++;
    }
    
    public synchronized int getCount() {
        return count;
    }
}

synchronized 區塊

public class Counter {
    private int count = 0;
    private final Object lock = new Object();
    
    public void increment() {
        synchronized (lock) {
            count++;
        }
    }
}

更多說明請參考 Java 執行緒同步

執行緒池

使用 ExecutorService 管理執行緒:

import java.util.concurrent.*;

// 固定大小的執行緒池
ExecutorService executor = Executors.newFixedThreadPool(4);

// 提交任務
executor.execute(() -> System.out.println("任務 1"));
executor.execute(() -> System.out.println("任務 2"));

// 有回傳值的任務
Future<String> future = executor.submit(() -> "結果");
String result = future.get();

// 關閉執行緒池
executor.shutdown();
executor.awaitTermination(60, TimeUnit.SECONDS);

常用執行緒池

// 固定大小
ExecutorService fixed = Executors.newFixedThreadPool(4);

// 單一執行緒
ExecutorService single = Executors.newSingleThreadExecutor();

// 快取(按需建立)
ExecutorService cached = Executors.newCachedThreadPool();

// 排程
ScheduledExecutorService scheduled = Executors.newScheduledThreadPool(2);
scheduled.schedule(() -> System.out.println("延遲執行"), 5, TimeUnit.SECONDS);
scheduled.scheduleAtFixedRate(() -> System.out.println("定期執行"), 0, 1, TimeUnit.SECONDS);

更多說明請參考 Java Executor

volatile

確保變數的可見性:

public class StopThread {
    private volatile boolean running = true;
    
    public void run() {
        while (running) {
            // 執行任務
        }
    }
    
    public void stop() {
        running = false;
    }
}

執行緒安全的集合

// 同步包裝
List<String> syncList = Collections.synchronizedList(new ArrayList<>());

// 並行集合
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
BlockingQueue<String> queue = new LinkedBlockingQueue<>();

更多說明請參考 Java 並行集合

完整範例

生產者消費者

import java.util.concurrent.*;

public class ProducerConsumer {
    public static void main(String[] args) {
        BlockingQueue<Integer> queue = new LinkedBlockingQueue<>(10);
        
        // 生產者
        Thread producer = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    queue.put(i);
                    System.out.println("生產:" + i);
                } catch (InterruptedException e) {
                    break;
                }
            }
        });
        
        // 消費者
        Thread consumer = new Thread(() -> {
            while (true) {
                try {
                    Integer item = queue.take();
                    System.out.println("消費:" + item);
                } catch (InterruptedException e) {
                    break;
                }
            }
        });
        
        producer.start();
        consumer.start();
    }
}

批次處理

ExecutorService executor = Executors.newFixedThreadPool(4);

List<Future<String>> futures = new ArrayList<>();

for (int i = 0; i < 10; i++) {
    final int taskId = i;
    Future<String> future = executor.submit(() -> {
        Thread.sleep(1000);
        return "任務 " + taskId + " 完成";
    });
    futures.add(future);
}

// 等待所有結果
for (Future<String> future : futures) {
    System.out.println(future.get());
}

executor.shutdown();

注意事項

  1. 避免死鎖:注意鎖的順序
  2. 使用執行緒池:不要直接建立大量執行緒
  3. 正確處理中斷:檢查 interrupted 狀態
  4. 使用並行集合:而不是自己同步