Java Thread to ExecutorService Opmize SwingUI

Published: 2026-06-09
Google AdSense 广告位 (待申请通过后开启)

Why is thread optimization necessary?

Traditional writing methods can cause problems if not handled properly.

🏢 A vivid analogy: Imagine you're doing business at a bank.

Your previous approach (infinite multithreading): The bank didn't have permanent tellers.

Every time a customer came (clicked a button), the bank temporarily hired a new employee (new Thread()) to serve them.

After serving that customer, the employee was immediately dismissed (thread destroyed).

With continuous clicks or a slow network: If 100 customers arrived, or network congestion caused slow processing,

the bank lobby would instantly be overcrowded with 100 temporary employees.

Everyone would be crammed together, competing for space and air (CPU and memory resources),

ultimately causing the bank to crash. Optimized approach (single-thread pool): The bank assigned a dedicated,

permanent VIP teller (SingleThreadExecutor) to the lobby.

With continuous clicks or a slow network: Regardless of the number of customers,

they must all line up at the entrance (blocking queue). There's only one teller,

who processes transactions one by one in order. The lobby will never be overcrowded,

the bank will always operate smoothly, and it will never crash due to overcrowding.

Frequent Thread Creation and Destruction (A Fatal Performance Bottleneck):

Each call to the `setGitMessageEvent` method creates a new thread.

Consequence: Threads are a very resource-intensive component in the operating system.

Frequent thread creation and destruction causes the CPU to waste a significant amount of time on thread context switching and memory allocation instead of actually executing business logic.

If this event is triggered frequently (e.g., when a user types in an input box or clicks repeatedly), resource consumption will spike rapidly.

Let's take an example.

before

  private void setGitMessageEvent(String cmd)
  {
    GitMessageCommandThread gitMessageCommandThread = new GitMessageCommandThread(cmd);
    new Thread(gitMessageCommandThread).start();
  }
  
  class GitMessageCommandThread
    extends Thread
  {
    String cmd = null;
    
    public GitMessageCommandThread(String cmd)
    {
      this.cmd = cmd;
    }
    
    public void run()
    {
      Gitgui.this.setMessage(this.cmd);
    }
  }
  
  public void setMessage(String cmd)
  {
    String s = Shell.send(cmd, getIdForm());
    this.textArea.setText(s);
    this.textArea.setSelectionStart(1);
    if (this.textArea.getCaretPosition() != 0) {
      this.textArea.setCaretPosition(1);
    }
    this.textField_2.setText(cmd);
  }

Is this threading approach efficient? No, it's inefficient and a classic example of a bad practice in Java programming. It not only has efficiency issues but also introduces code redundancy and potential UI freezes/crashes. The specific reasons are as follows: ❌ Problem 1. Frequent thread creation and destruction (a fatal efficiency bottleneck) In the `setGitMessageEvent` method, a new thread is created every time it's called. Consequence: Threads are very resource-intensive in the operating system. Frequent thread creation and destruction causes the CPU to waste a significant amount of time on thread context switching and memory allocation instead of actually executing business logic. If this event is triggered frequently (e.g., when a user types in an input box or clicks repeatedly), resource consumption will spike rapidly. 2. Severe Code Redundancy (Creating an Extra Thread Object): Consider these two lines of code: `javaGitMessageCommandThread gitMessageCommandThread = new GitMessageCommandThread(cmd);`

`new Thread(gitMessageCommandThread).start();`

Use code with caution. Problem: Your `GitMessageCommandThread` already inherits from `Thread`. It is itself a thread, and you've passed it as a `Runnable` to another `new Thread()`. Consequence: This is equivalent to creating an extra thread object unnecessarily, a low-level syntactic redundancy.

3. Thread Safety Risk (Illegal Multithreaded Operations on UI Components): In the `setMessage` method, there are `this.textArea.setText(s);` and `this.textField_2.setText(cmd);`. Problem: Judging from the component name, this is most likely a Java Swing or AWT-developed interface. In Java graphical interface development, it is absolutely forbidden to directly modify UI components in a child thread. Consequences: This can lead to strange refresh errors, flickering text, or even the entire software freezing and becoming unresponsive. 🛠️ The correct and efficient approach in actual development is to use a thread pool (ExecutorService) to reuse threads and combine it with SwingUtilities.invokeLater to safely update the interface.

opmize after

  private final ExecutorService gitCommandExecutor = Executors.newSingleThreadExecutor();

	private void setGitMessageEvent(String cmd) {
		gitCommandExecutor.submit(() -> {
			Gitgui.this.setMessage(cmd);
		});
	}

	public void setMessage(String cmd) {
		String s = Shell.send(cmd, getIdForm());

		javax.swing.SwingUtilities.invokeLater(() -> {
			this.textArea.setText(s);
			this.textArea.setSelectionStart(1);
			if (this.textArea.getCaretPosition() != 0) {
				this.textArea.setCaretPosition(1);
			}
			this.textField_2.setText(cmd);
		});
	}

💡 Benefits of the optimization: Extremely high performance: Only one background thread is used, so no matter how many times you trigger an event, they will be queued and executed, completely eliminating the overhead of creating threads. Safe and stable: UI updates are wrapped in SwingUtilities.invokeLater, ensuring that the interface will never freeze or cause rendering conflicts. Concise code: Bulky inner classes have been removed, making the logic clear at a glance.

Explore More

Technology Guides →

Java 21 Virtual Threads vs Java 17 Thread Pools in Swing Applications

Building a Postman-Like API Client: Go Fyne vs Java Swing

Oracle vs IBM: Who Would Have Been the Better Steward of Java?

Building a Linux Command Search Tool with Java Swing

Southeast Asia Insights →