You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Java线程从BLOCKED状态恢复为RUNNABLE状态?

解决多线程弹窗程序的线程阻塞问题

嘿,这个问题我之前整蛊朋友的时候也踩过坑!核心原因是你在**非事件调度线程(EDT)**里直接创建和操作Swing组件——Swing是单线程模型的,所有UI相关的操作必须在EDT中执行,多个线程同时抢着执行UI操作就会触发内部锁,导致除了一个线程外,其他全被阻塞。

问题根源拆解

你的Spam构造函数里,每个线程都在自己的线程循环中直接创建JFrame并调用setVisible(true),这些操作属于UI操作,Swing内部会强制要求这些操作在EDT中执行。当多个线程同时尝试执行这些UI操作时,它们会竞争EDT的执行权限,最终只有一个线程能拿到锁进入RUNNABLE状态,其他线程都被阻塞在BLOCKED状态,自然弹窗速率提不上来。

解决方案:把UI操作交给EDT处理

我们需要让线程只负责生成弹窗的随机参数(位置、颜色),而实际创建窗口、设置属性的UI操作,交给Swing的EDT来执行。可以用SwingUtilities.invokeLater()方法把UI任务提交到EDT的任务队列中,EDT会按顺序处理这些任务,同时你的工作线程可以继续生成新的任务,不会被阻塞。

修改后的代码示例

1. 优化线程类MyThread
import javax.swing.*;
import java.awt.*;
import java.util.Random;

public class MyThread implements Runnable {
    @Override
    public void run() {
        Random r = new Random();
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        
        while (!Thread.currentThread().isInterrupted()) {
            // 生成随机参数(每个线程有独立Random实例,线程安全)
            int x = Math.max(0, r.nextInt((int) screenSize.getWidth()) - 100);
            int y = Math.max(0, r.nextInt((int) screenSize.getHeight()) - 100);
            Color randomColor = new Color(r.nextInt(256), r.nextInt(256), r.nextInt(256));
            
            // 把UI操作提交到EDT执行
            SwingUtilities.invokeLater(() -> {
                JFrame window = new JFrame();
                window.setSize(100, 100);
                window.setLocation(x, y);
                window.setBackground(randomColor);
                window.setVisible(true);
            });
            
            // 加微小延迟,避免EDT过载,同时控制弹窗速率
            try {
                Thread.sleep(8);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                break;
            }
        }
    }
}
2. 主类Init保持不变
import java.util.ArrayList;

public class Init {
    public static void main(String[] args) throws InterruptedException {
        ArrayList<Thread> list = new ArrayList<>();
        for(int i = 0; i < 4; i++) {
            Thread t = new Thread(new MyThread());
            t.start();
            list.add(t);
        }
        
        Thread.sleep(1000);
        for(Thread t : list) {
            System.out.println(t.getName() + " " + t.getState());
        }
    }
}

修改后效果说明

  • 现在每个工作线程只负责生成随机参数,然后提交UI任务到EDT,线程本身不会执行任何UI操作,所以不会被阻塞,状态会是RUNNABLE或者TIMED_WAITING(sleep的时候)。
  • EDT会批量处理这些UI任务,弹窗速率会明显提升,因为多个线程同时在生成任务,EDT会尽可能快地处理它们。
  • 加了Math.max(0, x)避免窗口跑到屏幕外,小延迟Thread.sleep(8)可以防止EDT被瞬间塞满导致系统卡顿,你可以根据需要调整这个延迟时间来控制弹窗速度。

内容的提问来源于stack exchange,提问作者Papermage11

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:42:08