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

Java 多線程實現非阻塞等待提示框

     編輯:Java 相關知識

前言

Java 自 1995 年問世以來,憑藉簡單性、面向對象、平台無關性及多線程支持等優勢,迅速成為全球最熱門的程式語言之一。在 GUI 應用開發中,妥善處理耗時任務而不凍結介面,是提升用戶體驗的關鍵。本文將示範如何利用 Java 多線程機制,實現一個「正在執行,請等待」的非阻塞提示框。

問題背景

在 Java 桌面應用中,若在事件分派執行緒(EDT)上直接執行大量資料庫交換、複雜運算或遠程伺服器連線等耗時操作,會導致介面無法重繪、滑鼠點擊無響應,甚至出現「未回應」的假象。這在專業軟體中是不可接受的。

解決思路

採用「工作者執行緒 + 提示框執行緒 + 監控執行緒」三線程協作模式:

  • 工作者執行緒:負責實際的耗時業務邏輯。
  • 提示框執行緒:啟動一個模態 JDialog 顯示等待資訊,並將游標設為等待狀態。
  • 監控執行緒:呼叫 Thread.join() 等待工作者執行緒結束,隨後自動關閉提示框。

此架構確保 EDT 始終保持響應,同時提示框能準確反映後台任務狀態。

核心程式碼實現

1. 主視窗類 TestFrame

建立包含「開始執行緒」按鈕的主視窗,按鈕事件中啟動三個執行緒:

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

public class TestFrame extends JFrame {
    private JPanel testPanel;
    private JButton testButton;

    public TestFrame() {
        // 設定 Windows 外觀
        try {
            UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
        } catch (Exception ex) {
            System.out.println("LookAndFeel 設定失敗: " + ex);
        }

        // 視窗置中、尺寸為螢幕一半
        Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
        setSize(dim.width / 2, dim.height / 2);
        setLocation(dim.width / 4, dim.height / 4);

        testPanel = new JPanel();
        testButton = new JButton("開始執行緒");
        testPanel.add(testButton);
        getContentPane().add(testPanel);

        // 按鈕事件:啟動工作者執行緒、提示框執行緒
        testButton.addActionListener(e -> {
            TestThread worker = new TestThread();
            worker.start();
            new ThreadDiag(this, worker, "正在執行,請等待......").start();
        });

        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) { System.exit(0); }
        });
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            TestFrame f = new TestFrame();
            f.setTitle("執行緒等待測試");
            f.setVisible(true);
        });
    }
}

2. 工作者執行緒 TestThread

模擬耗時運算:在標準輸出列印 1 到 99999。

public class TestThread extends Thread {
    @Override
    public void run() {
        for (int i = 1; i < 100000; i++) {
            System.out.println(i);
        }
    }
}

3. 提示框執行緒 ThreadDiag

建立模態對話框,啟動監控執行緒 DisposeDiag。

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

public class ThreadDiag extends Thread {
    private final Thread workerThread;
    private final JFrame parent;
    private final String message;
    private JDialog dialog;

    public ThreadDiag(JFrame parent, Thread workerThread, String message) {
        this.parent = parent;
        this.workerThread = workerThread;
        this.message = message;
        initDialog();
    }

    private void initDialog() {
        dialog = new JDialog(parent, "正在執行,請等待...", true);
        dialog.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
        JPanel panel = new JPanel();
        panel.add(new JLabel(message));
        dialog.getContentPane().add(panel);
        new DisposeDiag(workerThread, dialog).start(); // 監控執行緒
    }

    @Override
    public void run() {
        Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
        int w = dim.width / 4, h = 60;
        dialog.setSize(w, h);
        dialog.setLocation((dim.width - w) / 2, (dim.height - h) / 2);
        dialog.setVisible(true); // 阻塞直到 dispose()
    }
}

4. 監控執行緒 DisposeDiag

等待工作者執行緒結束,然後釋放提示框資源。

class DisposeDiag extends Thread {
    private final Thread target;
    private final JDialog dialog;

    public DisposeDiag(Thread target, JDialog dialog) {
        this.target = target;
        this.dialog = dialog;
    }

    @Override
    public void run() {
        try {
            target.join(); // 等待工作者結束
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            SwingUtilities.invokeLater(() -> dialog.dispose());
        }
    }
}

執行結果

點擊按鈕後,中央顯示「正在執行,請等待......」模態對話框,主視窗仍可移動、最小化;控制檯高速輸出數字。當迴圈結束,對話框自動消失,程式恢復正常互動。

執行畫面截圖

總結

此範例展示了經典的「背景執行緒 + 玻璃窗/模態對話框」模式,適用於 JDK 1.3 及以上版本。實務上可進一步封裝為可復用的 WaitingDialog 工具類,支援進度條、取消操作等進階功能。

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