- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我的问题与this有关问题,已经有了答案:
yes, there is a happens-before relationship imposed between actionsof the thread calling
invokeLater
/invokeAndWait
and actions on theEDT of the runnable thereby submitted.
invokeAndWait
,这样它才能正常工作,但不会强加发生在之前的关系?通过正常工作的方法,我的意思如下:
Runnable
保证只执行一次。 Runnable
在特定线程上执行。 Runnable
已完成。 Runnable
执行后返回已完成。 最佳答案
这里最难的要求是:
The submitted
Runnable
is guaranteed to be executed exactly once.
volatile
(Plain) 字段将工作任务从提交者转移到执行者不会创建发生之前的关系,但也不能保证执行者完全或在有限的时间内看到任务。编译器将能够优化对该字段的分配,或者在运行时执行程序线程可能只从其缓存而不是从主内存中读取值。
invokeAndWait
方法是不可能的”(除非可能使用 native 代码)。
volatile
弱,但仍提供以下保证:
- Progress. Writes are eventually visible.
[...]
For example in constructions in which the only modification of some variable x is for one thread to write in Opaque (or stronger) mode,X.setOpaque(this, 1)
, any other thread spinning inwhile(X.getOpaque(this)!=1){}
will eventually terminate.
[...]
Note that this guarantee does NOT hold in Plain mode, in which spin loops may (and usually do) infinitely loop [...]
invokeAndWait
方法时,您还必须考虑启动线程之前的操作发生在该线程 (
JLS §17.4.4 ) 中的第一个操作之前。所以工作线程必须在构造 Action 之前启动。
final
字段语义”(
JLS §17.15.1 )。当
invokeAndWait
的调用者以 lambda 表达式的形式创建
Runnable
时,该 lambda 对变量的捕获具有(据我所知)隐式
final
字段语义。
If so, please include an example implementation, which proves this.
invokeAndWait
的(简化的)潜在实现。请注意,我并不完全熟悉 Java 内存模型,因此代码中可能存在错误。
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
class OpaqueExecutor {
// For simplicity assume there will every only be a single work task
// So pending task being replaced by other task is not an issue
private final AtomicReference<Runnable> nextTask = new AtomicReference<>();
public OpaqueExecutor() {
Thread worker = new Thread(() -> {
while (true) {
// Use getOpaque() to no create happens-before relationship
Runnable task = nextTask.getOpaque();
if (task == null) {
// For efficiency indicate to the JVM that this is busy-waiting
Thread.onSpinWait();
} else {
// Clear pending task; memory mode here does not matter because we only want
// to guarantee that this thread does not see task again
nextTask.setPlain(null);
task.run();
}
}
}, "Worker thread");
worker.setDaemon(true);
worker.start();
}
public void invokeLater(Runnable runnable) {
// For simplicity assume that there is no existing pending task which could be
// replaced by this
// Use setOpaque(...) to not create happens-before relationship
nextTask.setOpaque(runnable);
}
private static class Task implements Runnable {
private final AtomicBoolean isFinished = new AtomicBoolean(false);
// Must NOT be final to prevent happens-before relationship from
// final field semantics
private Runnable runnable;
public Task(Runnable runnable) {
this.runnable = runnable;
}
public void run() {
try {
runnable.run();
} finally {
// Use setOpaque(...) to not create happens-before relationship
isFinished.setOpaque(true);
}
}
public void join() {
// Use getOpaque() to no create happens-before relationship
while (!isFinished.getOpaque()) {
// For efficiency indicate to the JVM that this is busy-waiting
Thread.onSpinWait();
}
}
}
public void invokeAndWait(Runnable runnable) {
Task task = new Task(runnable);
invokeLater(task);
task.join();
}
public static void main(String... args) {
// Create executor as first step to not create happens-before relationship
// for Thread.start()
OpaqueExecutor executor = new OpaqueExecutor();
final int expectedValue = 123;
final int expectedNewValue = 456;
class MyTask implements Runnable {
// Must NOT be final to prevent happens-before relationship from
// final field semantics
int value;
public MyTask(int value) {
this.value = value;
}
public void run() {
int valueL = value;
if (valueL == expectedValue) {
System.out.println("Found expected value");
} else {
System.out.println("Unexpected value: " + valueL);
}
value = expectedNewValue;
}
}
MyTask task = new MyTask(expectedValue);
executor.invokeAndWait(task);
int newValue = task.value;
if (newValue == expectedNewValue) {
System.out.println("Found expected new value");
} else {
System.out.println("Unexpected new value: " + newValue);
}
}
}
关于Java 发生在关系 invokeAndWait 之前,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64497416/
发生在后台的进程会触发回调以询问各种问题。 在这种情况下,问题是“可以迁移您的数据吗?”,所以我必须询问用户。由于我们必须在 EDT 上完成所有 Swing 工作,因此最终看起来像这样(我只删除了注释
这个问题在这里已经有了答案: invokeAndWait method in SwingUtilities (2 个答案) 关闭 9 年前。 谁能告诉我这两个代码之间的实际区别是什么,因为它们都产生
我的问题与this有关问题,已经有了答案: yes, there is a happens-before relationship imposed between actionsof the thre
以下代码运行良好 abstract class FunctionRunnable implements Runnable { protected abstract V calculate();
我正在尝试保存 JFrame 的 .PNG 图像。在 JFrame 中,我有两个 Plot3DPanel 对象。很可能是因为同步错误,在保存 .PNG 时左侧尺寸的框架是不可见的。 因此,我使用以下代
run() 方法中的代码未被执行。谁能告诉我为什么? startButton.addActionListener(new ActionListener() { public v
我的 previous problem 有问题.我在代码库的其他地方也有代码 SwingUtillities.invokeAndWait,但是当我删除它时,gui 不会刷新。如果我不删除它,我得到的错
我在某处读到,对于任何影响 gui 视觉效果的线程,它都应该使用 SwingUtilities.invokeAndWait/invokeLater 在 EDT 中运行 对于基本的 gui,是否有必要使
SwingUtilities.invokeAndWait() 抛出一个 InterruptedException 和一个 InvocationTargetException 我应该如何处理这些? p
当 Runnable 与 SwingUtilities.invokeAndWait() 一起使用时是否创建了一个新线程? 最佳答案 不,当 Runnable 与 SwingUtilities.invo
请解释 SwingUtilities 中的 invokeAndWait() 方法。我无法理解这一点。解释的很清楚。 如果你用一个例子来尝试会很有帮助。 编辑添加@noob的问题扩展: this 有什么
我在this post中提到的问题实际上是由于跨线程 GUI 问题而发生的(我希望如此)。 您能帮我处理 Java 版本的操作委托(delegate)吗? 在 C# 中,它是这样内联完成的:
我有一个在多个线程上运行的 Swing 应用程序,我在 EDT 上创建了 Swing 组件。 Executor 会在某个时刻启动将文本插入到 JTextArea 的线程。但是,与 InvokeAndW
很确定是这样 - 但我想确定 -是在 invokeLater() 或 invokeAndWait() 的情况下给出的 happens-before 关系? 这些方法在(分别为 SwingUtiliti
我一直在使用以下方法创建组件并从 Swing 向/从 EDT 外部返回值。例如,以下方法可以是 JFrame 的扩展,以创建一个 JPanel 并将其添加到父级 JFrame: public JPan
我偶然发现了一个使用 invokeAndWait 的问题。下面的示例代码说明了这个问题。谁能详细说明发生了什么?为什么 lambda 表达式挂起而匿名内部类和方法 ref 没有挂起。 public c
我创建了一个 Swing GUI,它是从其他 Java 类文件调用的。 GUI 的构造函数: public AdviceGUI(AdviceModel model) throws Invocation
我有这个代码: try { SwingUtilities.invokeAndWait(new Runnable() { public void run() {
我正在使用 Eclipse RCP 和 Swing 开发一个项目。我看到两对方法 invokeLater()/invokeAndWait() 和 asyncExec()/syncExec() 被大量使
编辑:我已经提到了这个link并且我能够理解 InvokeLater 的代码流。我的问题是,为什么这个逻辑是这样实现的?有什么具体原因吗? 以下是我的代码: private void init()
我是一名优秀的程序员,十分优秀!