- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我有一个 Java 程序,它在一个单独的(非 EDT)线程上执行一个紧密循环。虽然我认为 Swing UI 应该仍然是响应式的,但事实并非如此。下面的示例程序展示了这个问题:单击“试试我”按钮应该会在大约半秒后弹出一个对话框,并且应该可以通过单击它的任何响应立即关闭该对话框。相反,对话框需要更长的时间才能出现,和/或在单击其中一个按钮后需要很长时间才能关闭。
有谁知道为什么 EDT 处理被延迟,即使只有一个繁忙的线程?
(请注意,尽管对 Thread.sleep
调用的各种建议是问题的原因,但事实并非如此。它可以被删除并且问题仍然可以重现,尽管它表现得轻微不太频繁并且通常表现出上述第二种行为 - 即无响应的 JOptionPane
对话框而不是延迟的对话框外观。此外,没有理由让 sleep 调用屈服于另一个线程,因为 如上所述,有备用处理器内核;在调用 sleep
之后,EDT 可以继续在另一个内核上运行。
import java.awt.EventQueue;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
public class MFrame extends JFrame
{
public static void main(String[] args)
{
EventQueue.invokeLater(() -> {
new MFrame();
});
}
public MFrame()
{
JButton tryme = new JButton("Try me!");
tryme.addActionListener((e) -> {
Thread t = new Thread(() -> {
int a = 4;
for (int i = 0; i < 100000; i++) {
for (int j = 0; j < 100000; j++) {
a *= (i + j);
a += 7;
}
}
System.out.println("a = " + a);
});
t.start();
// Sleep to give the other thread a chance to get going.
// (Included because it provokes the problem more reliably,
// but not necessary; issue still occurs without sleep call).
try {
Thread.sleep(500);
}
catch (InterruptedException ie) {
ie.printStackTrace();
}
// Now display a dialog
JOptionPane.showConfirmDialog(null, "You should see this immediately");
});
getContentPane().add(tryme);
pack();
setVisible(true);
}
}
更新:问题仅发生在服务器 VM 上(但请参阅进一步更新)。指定客户端 VM(-client
java 可执行文件的命令行参数)似乎可以抑制问题(更新 2)在一台机器上而不是另一台 .
更新 3:单击按钮后,我看到 Java 进程使用了 200% 的处理器,这意味着有 2 个处理器内核已满载。这对我来说根本没有意义。
更新 4: 也发生在 Windows 上。
更新 5:使用调试器 (Eclipse) 证明是有问题的;调试器似乎无法停止线程。这是非常不寻常的,我怀疑 VM 中存在某种活锁或竞争条件,因此我已向 Oracle 提交了一个错误(评论 ID JI-9029194)。
更新 6: 我找到了 my bug report in the OpenJDK bug database . (我没有被告知它已被接受,我不得不搜索它)。那里的讨论最有趣,并且已经阐明了导致此问题的可能原因。
最佳答案
我在 Mac OS X 上看到了相同的效果。虽然您的示例已正确同步,但您看到的平台/JVM 可变性可能是由于线程调度方式的变化无常,导致饥饿。添加Thread.yield()
到 t
中的外循环可以缓解这个问题,如下所示。除了示例的人为性质,像 Thread.yield()
这样的提示将 not通常需要。无论如何,请考虑 SwingWorker
, 如图所示 here出于演示目的执行类似的紧密循环。
I do not believe that
Thread.yield()
should need to be called in this case at all, despite the artificial nature of the test case, however.
正确;屈服只是暴露了潜在的问题:t
starves事件派发线程。请注意,在下面的示例中,即使没有 Thread.yield()
,GUI 也会立即更新。如本相关 Q&A 中所述,您可以尝试降低线程的优先级。或者,按照建议在单独的 JVM 中运行 t
here使用 ProcessBuilder
,它也可以在 SwingWorker
的后台运行,如图 here .
but why?
所有支持的平台都建立在单线程图形库上。阻塞、饿死或饱和管理事件分派(dispatch)线程是相当容易的。重要的后台任务通常会隐式产生,例如在发布中间结果、阻塞 I/O 或等待工作队列时。一个不做的任务可能必须显式地让出。
import java.awt.EventQueue;
import javax.swing.JButton;
import javax.swing.JFrame;
public class MFrame extends JFrame {
private static final int N = 100_000;
private static final String TRY_ME = "Try me!";
private static final String WORKING = "Working…";
public static void main(String[] args) {
EventQueue.invokeLater(new MFrame()::display);
}
private void display() {
JButton tryme = new JButton(TRY_ME);
tryme.addActionListener((e) -> {
Thread t = new Thread(() -> {
int a = 4;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
a *= (i + j);
a += 7;
}
Thread.yield();
}
EventQueue.invokeLater(() -> {
tryme.setText(TRY_ME);
tryme.setEnabled(true);
});
System.out.println("a = " + a);
});
t.start();
tryme.setEnabled(false);
tryme.setText(WORKING);
});
add(tryme);
pack();
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
}
关于java - 其他线程中的忙循环延迟了 EDT 处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35154352/
我将 Bootstrap 与 css 和 java 脚本结合使用。在不影响前端代码的情况下,我真的很难在css中绘制这个背景。在许多问题中,人们将宽度和高度设置为 0%。但是由于我的导航栏,我不能使用
我正在用 c 编写一个程序来读取文件的内容。代码如下: #include void main() { char line[90]; while(scanf("%79[^\
我想使用 javascript 获取矩阵数组的所有对 Angular 线。假设输入输出如下: input = [ [1,2,3], [4,5,6], [7,8,9], ] output =
可以用pdfmake绘制lines,circles和other shapes吗?如果是,是否有documentation或样本?我想用jsPDF替换pdfmake。 最佳答案 是的,有可能。 pdfm
我有一个小svg小部件,其目的是显示角度列表(参见图片)。 现在,角度是线元素,仅具有笔触,没有填充。但是现在我想使用一种“内部填充”颜色和一种“笔触/边框”颜色。我猜想line元素不能解决这个问题,
我正在为带有三角对象的 3D 场景编写一个非常基本的光线转换器,一切都工作正常,直到我决定尝试从场景原点 (0/0/0) 以外的点转换光线。 但是,当我将光线原点更改为 (0/1/0) 时,相交测试突
这个问题已经有答案了: Why do people write "#!/usr/bin/env python" on the first line of a Python script? (22 个回
如何使用大约 50 个星号 * 并使用 for 循环绘制一条水平线?当我尝试这样做时,结果是垂直(而不是水平)列出 50 个星号。 public void drawAstline() { f
这是一个让球以对角线方式下降的 UI,但球保持静止;线程似乎无法正常工作。你能告诉我如何让球移动吗? 请下载一个球并更改目录,以便程序可以找到您的球的分配位置。没有必要下载足球场,但如果您愿意,也可以
我在我的一个项目中使用 Jmeter 和 Ant,当我们生成报告时,它会在报告中显示 URL、#Samples、失败、成功率、平均时间、最短时间、最长时间。 我也想在报告中包含 90% 的时间线。 现
我有一个不寻常的问题,希望有人能帮助我。我想用 Canvas (android) 画一条 Swing 或波浪线,但我不知道该怎么做。它将成为蝌蚪的尾部,所以理想情况下我希望它的形状更像三角形,一端更大
这个问题已经有答案了: Checking Collision of Shapes with JavaFX (1 个回答) 已关闭 8 年前。 我正在使用 JavaFx 8 库。 我的任务很简单:我想检
如何按编号的百分比拆分文件。行数? 假设我想将我的文件分成 3 个部分(60%/20%/20% 部分),我可以手动执行此操作,-_-: $ wc -l brown.txt 57339 brown.tx
我正在努力实现这样的目标: 但这就是我设法做到的。 你能帮我实现预期的结果吗? 更新: 如果我删除 bootstrap.css 依赖项,问题就会消失。我怎样才能让它与 Bootstrap 一起工作?
我目前正在构建一个网站,但遇到了 transform: scale 的问题。我有一个按钮,当用户将鼠标悬停在它上面时,会发生两件事: 背景以对 Angular 线“扫过” 按钮标签颜色改变 按钮稍微变
我需要使用直线和仿射变换绘制大量数据点的图形(缩放图形以适合 View )。 目前,我正在使用 NSBezierPath,但我认为它效率很低(因为点在绘制之前被复制到贝塞尔路径)。通过将我的数据切割成
我正在使用基于 SVM 分类的 HOG 特征检测器。我可以成功提取车牌,但提取的车牌除了车牌号外还有一些不必要的像素/线。我的图像处理流程如下: 在灰度图像上应用 HOG 检测器 裁剪检测到的区域 调
我有以下图片: 我想填充它的轮廓(即我想在这张图片中填充线条)。 我尝试了形态学闭合,但使用大小为 3x3 的矩形内核和 10 迭代并没有填满整个边界。我还尝试了一个 21x21 内核和 1 迭代,但
我必须找到一种算法,可以找到两组数组之间的交集总数,而其中一个数组已排序。 举个例子,我们有这两个数组,我们向相应的数字画直线。 这两个数组为我们提供了总共 7 个交集。 有什么样的算法可以帮助我解决
简单地说 - 我想使用透视投影从近裁剪平面绘制一条射线/线到远裁剪平面。我有我认为是使用各种 OpenGL/图形编程指南中描述的方法通过单击鼠标生成的正确标准化的世界坐标。 我遇到的问题是我的光线似乎
我是一名优秀的程序员,十分优秀!