首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 多線程程式設計完整指南:從基礎 Timer 到 Thread 進階應用

     編輯:Java 相關知識

Java 平台自誕生之初即被設計為多線程環境。當主程式執行時,垃圾回收、事件處理等系統級任務已在背景悄然運作,這些本質上都是線程。多線程讓開發者能定義相互獨立、互不干擾的任務,系統透過 CPU 時間片輪換,讓這些任務看似同時執行。

核心類別與介面概覽

Java 提供四大核心工具支援多線程開發:

  • java.util.Timer:適合簡單的週期性任務排程
  • javax.swing.Timer:專為 Swing GUI 更新設計,執行於事件派發線程
  • Thread 類別:提供底層線程控制能力
  • Runnable 介面:支援任務與線程分離,突破單一繼承限制

Timer 排程:輕量級週期任務

java.util.Timer 適合「每 500 毫秒執行一次」這類簡單需求。任務邏輯封裝於 TimerTask 的 run() 方法中:

import java.util.*;

public class Hi {
    public static void main(String[] args) throws java.io.IOException {
        TimerTask task = new TimerTask() {
            public void run() {
                System.out.println("Hi");
            }
        };
        Timer timer = new Timer();
        timer.schedule(task, 0, 500); // 立即啟動,每 500ms 執行一次
        System.out.println("Press ENTER to stop");
        System.in.read(new byte[10]);
        timer.cancel();
    }
}

關鍵點:JVM 只要有非守護線程存活就不會退出。timer.cancel() 終止排程線程後,程式才會結束。

Swing Timer:GUI 安全的週期更新

javax.swing.Timer 與 java.util.Timer 運作類似,但兩大差異:

  1. 任務由 ActionListener 定義
  2. 執行於事件派發線程 (EDT),確保 Swing 元件更新的執行緒安全

Swing 採單線程模型,所有元件操作必須在 EDT 執行。以下範例每 0.5 秒更新標籤計數:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Count {
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Container contentPane = frame.getContentPane();
        final JLabel label = new JLabel("", JLabel.CENTER);
        label.setFont(new Font("Serif", Font.PLAIN, 36));
        contentPane.add(label, BorderLayout.CENTER);
        
        ActionListener listener = new ActionListener() {
            int count = 0;
            public void actionPerformed(ActionEvent e) {
                count++;
                label.setText(Integer.toString(count));
            }
        };
        Timer timer = new Timer(500, listener);
        timer.start();
        frame.setSize(300, 100);
        frame.setVisible(true);
    }
}

計數器執行結果

Thread 類別:完全掌控的長時間任務

當任務非單純重複、需長時間執行(如網路下載),Thread 類別提供完整控制權。兩種實作方式:

  1. 繼承 Thread 並覆寫 run()
  2. 實作 Runnable 介面,傳入 Thread 建構子

因 Java 單一繼承限制,若類別已繼承其他類別,必須採用 Runnable 方式。

綜合範例:並行下載與列印

以下程式同時啟動兩個線程:thread1 下載 URL 內容並統計字元數,thread2 週期性列印訊息。主線程等待使用者輸入結束:

import java.io.*;
import java.net.*;

public class Both {
    public static void main(String[] args) {
        final String urlString = args[0];
        final String message = args[1];
        
        // 線程 1:下載並計算大小(匿名 Thread 子類別)
        Thread thread1 = new Thread() {
            public void run() {
                try {
                    URL url = new URL(urlString);
                    URLConnection connection = url.openConnection();
                    InputStreamReader isr = new InputStreamReader(connection.getInputStream());
                    BufferedReader reader = new BufferedReader(isr);
                    int count = 0;
                    while (reader.read() != -1) count++;
                    System.out.println("Size is: " + count);
                    reader.close();
                } catch (MalformedURLException e) {
                    System.err.println("Bad URL: " + urlString);
                } catch (IOException e) {
                    System.err.println("I/O Problems");
                }
            }
        };
        thread1.start();
        
        // 線程 2:週期性列印訊息(Runnable 實作)
        Runnable runnable = new Runnable() {
            public void run() {
                while (true) {
                    System.out.println(message);
                    try { Thread.sleep(500); } 
                    catch (InterruptedException e) {}
                }
            }
        };
        Thread thread2 = new Thread(runnable);
        thread2.start();
        
        // 主線程等待使用者輸入
        try {
            System.out.println("Press ENTER to stop");
            System.in.read(new byte[10]);
        } catch (IOException e) {
            System.out.println("I/O problems");
        }
        System.exit(0);
    }
}

選擇建議與總結

掌握多線程是成為高效 Java 開發者的關鍵。選擇原則:

  • 簡單週期任務 → java.util.Timer
  • Swing GUI 更新 → javax.swing.Timer
  • 需完整控制、長時間運算 → Thread + Runnable
  • 任務邏輯與線程控制分離 → 優先選 Runnable

越早理解線程運作機制,越能洞悉 Java 程式的並行行為與互動模式。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved