- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我继续阅读和研究练习书中的并发性,但我无法理解第 9.3.2 章中的示例。
本章介绍GUI应用程序开发。
作者在文中说,如果事件处理程序是长时间运行的任务 - 您可以在单独的线程中运行它以提高应用程序的响应能力。
作者在书中提供了以下代码:
后台任务:
abstract class BackgroundTask<V> implements Runnable, Future<V> {
private final FutureTask<V> computation = new Computation();
private class Computation extends FutureTask<V> {
public Computation() {
super(new Callable<V>() {
public V call() throws Exception {
return BackgroundTask.this.compute();
}
});
}
protected final void done() {
GuiExecutor.instance().execute(new Runnable() {
public void run() {
V value = null;
Throwable thrown = null;
boolean cancelled = false;
try {
value = get();
} catch (ExecutionException e) {
thrown = e.getCause();
} catch (CancellationException e) {
cancelled = true;
} catch (InterruptedException consumed) {
} finally {
onCompletion(value, thrown, cancelled);
}
}
;
});
}
}
protected void setProgress(final int current, final int max) {
GuiExecutor.instance().execute(new Runnable() {
public void run() {
onProgress(current, max);
}
});
}
// Called in the background thread
protected abstract V compute() throws Exception;
// Called in the event thread
protected void onCompletion(V result, Throwable exception,
boolean cancelled) {
}
protected void onProgress(int current, int max) {
}
// Other Future methods forwarded to computation
}
和runInBackground方法:
public void runInBackground(final Runnable task) {
startButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
class CancelListener implements ActionListener {
BackgroundTask<?> task;
public void actionPerformed(ActionEvent event) {
if (task != null)
task.cancel(true);
}
}
final CancelListener listener = new CancelListener();
listener.task = new BackgroundTask<Void>() {
public Void compute() {
while (moreWork() && !isCancelled())
doSomeWork();
return null;
}
public void onCompletion(boolean cancelled, String s,
Throwable exception) {
cancelButton.removeActionListener(listener);
label.setText("done");
}
};
cancelButton.addActionListener(listener);
backgroundExec.execute(task);
}
});
}
我无法理解这段代码的逻辑。根据我看到的代码,runInBackground
方法将监听器添加到 startButton,它在分离(非 Swing)中运行任务(作为 runInBackground
方法的参数传递)线程。
但是这个方法的其他代码我不清楚。根据书上的文字,我们应该有可能从 Swing 线程中断这个任务。但是在方法文本中,我们向 cancelButton 添加了额外的监听器,这使得工作与停止任务无关,该任务作为 runInBackground
方法参数传递。
请澄清一下。
最佳答案
Swing 本质上是单线程的。如果长时间运行的任务在 Event Dispatch Thread (EDT) 上排队,它将阻塞直到完成并阻止进一步的事件处理。如果 EDT 被阻塞,这将使 GUI 看起来“卡住”(至少在队列处理恢复之前)。
为避免这种情况,将非 GUI 工作放在其他线程上是一个很好的做法。通常,这些线程的创建是由 GUI 事件触发的,线程通过回调发出完成信号,因此可以根据需要更新 GUI。
在此示例中,CancelButton
上的按钮按下事件 确实 源自 EDT。但是,按下按钮的事件处理程序必须保留对 BackgroundTask
的引用,以便它可以调用 cancel(true)
方法。因此,当用户单击 startButton
时,会发生以下序列:
ActionListner
for startButton
由用户按下按钮触发。BackgroundTask
已创建。BackgroundTask
的新 ActionLister
附加到 cancelButton
BackgroundTask
已启动。如果用户点击取消按钮,附加的ActionLister
将在BackgroundTask
上调用cancel()
。
否则,一旦 BackgroundTask
完成,它就会删除 CancelListener
,因为取消已完成的任务将毫无意义。
有关 EDT 工作原理的更多信息,您可能需要查看以下问题:Java Event-Dispatching Thread explanation
EDIT 正如评论中指出的那样,Swing 组件通常不是线程安全的,它是 recommended they only be modified from the EDT .
乍一看,BackgroundTask
的 onCompletion()
方法似乎同时修改了 cancelButton
和 label
来自工作线程而不是 EDT。
然而,GuiExecutor
提供一个 execute()
方法,确保传入的 Runnable
在 EDT 上运行:
public void execute(Runnable r) {
if (SwingUtilities.isEventDispatchThread())
r.run();
else
SwingUtilities.invokeLater(r);
}
BackgroundTask
使用 execute()
方法调用其 onCompletion()
方法。因此,从 EDT 运行对 cancelButton
和 label
的修改。
因为 runInBackground
它也在操纵 Swing 组件,所以它也应该从 EDT 调用。
关于java - Concurrency runInBackground方法逻辑实战[9.3.2],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42559937/
当我尝试加载库 Raster 时,我收到如下错误: 错误:inDL(x, as.logic(local), as.logic(now), ...) 中的“raster”的包或命名空间加载失败:无法加载
当我尝试加载库 Raster 时,我收到如下错误: 错误:inDL(x, as.logic(local), as.logic(now), ...) 中的“raster”的包或命名空间加载失败:无法加载
望着help section about_Comparison_Operators of PowerShell我是这样理解的: PS C:\> $false,$false -eq $true PS C
我刚刚修改了旧代码,现在似乎没有任何效果。请您指导我哪里出错了。 一些不起作用的事情是: 以前,焦点始终停留在屏幕上唯一的输入字段上。 (现在不行了),代码中的 if else 条件也不起作用。 On
请帮我找到一个使用普通 'ol javascript 的解决方案(我无法使用外部框架)。此外,CSS :hover 选择器不适用于现实世界的实现。 注册事件发生的事情设置所有调用最后注册事件数组项。
我想创建一个软件来为残障 child 交通规划公交路线(及其最佳载客量)。 这些总线具有以下规范: m 个座位(最多 7 个 - 因为有司机和助理) o 轮椅“座位”(最多 4 个) 固定的最大负载量
有人能帮我吗?似乎我的 for 逻辑根本不起作用,因为它一直在上午 12:00 返回我的开始时间 这是我的代码 Sub forlogic() Dim i As Single Dim t
我正在尝试设置 OR两个切片器过滤器之间的逻辑。两个切片器来自相同的数据集。以下是更多详细信息: 我的源表: 带切片器的视觉效果: 我的目标是,如果我从切片器 1 和切片器 2 中选择任何值,我的视觉
我有以下 C 语句: int res = x & (x ^ y); 有没有办法做同样的事情,但每次只使用一次x和y? 例如: x | (~x & y) == x | y 最佳答案 是的,通过扩展 xo
我正在创建 Azure 逻辑应用程序以将新的 Sharepoint 文件添加到 Azure Blob。 Sharepoint 由我的公司运行,我使用我的凭据登录来为逻辑应用程序创建 Sharepoin
我有一个问题要求为给定函数合成最简单的乘积表达式总和。基本上,如果 AB == CD,则函数为 1,否则为 0,结果如下: (!A && !B && !C && !D) || (!A && B &&
我正在尝试确定是否可以在不溢出的情况下计算两个 32 位整数的总和,同时仅使用某些按位运算符和其他运算符。因此,如果整数 x 和 y 可以相加而不会溢出,则以下代码应返回 1,否则返回 0。 ((((
处理乍一看需要许多嵌套 if 语句的复杂业务逻辑的好方法是什么? 例子: 折扣券。可能: 1a) 超值折扣 1b) 百分比折扣 2a) 正常折扣 2b) 累进折扣 3a) 需要访问优惠券 3b) 不需
假设我有一个“numbers”对象数组,其中包含“startNo”整数和“endNo”整数。 数组中可以有多个“数字”,我想获取一个包含修改对象的新数组,该数组仅具有不重叠的范围。 例如:如果数组有:
我在这个问题上遇到了困难。我正在使用 JavaScript。 我有一个文本区域,用于检测 @ 输入并将其位置存储在数组中。 var input = "@a @b @c" //textarea var
默认 IN 使用 OR 基本逻辑。有没有办法在范围内使用 AND 基本逻辑。 例如下面的查询 SELECT ItemId,CategoryID FROM ItemCategories WHERE Ca
我想在您将鼠标悬停在网站图像上时添加叠加层。我在这里实现了这个,它工作正常http://jsfiddle.net/stujLbjh/ 这是js代码: var divs = document.query
这个问题在这里已经有了答案: Which is faster: x>2 是否比 x>>31 快?换句话说,sar x, 2 是否比 sar x, 31 快?我做了一些简单的测试,他们似乎有相同的速度
我有grails criteriaQuery,我在这里再次检查OR逻辑,就像这样一个状态变量: or { eq("status", Status.ONE) eq("status",
我有grails criteriaQuery,我在这里再次检查OR逻辑,就像这样一个状态变量: or { eq("status", Status.ONE) eq("status",
我是一名优秀的程序员,十分优秀!