Swingworker 实例未同时运行
我的计算机有 4 个核心,我正在运行 Java swing gui 程序。当我运行我的应用程序时,它仅使用两个核心,CPU 利用率约为 30%。我有大量文件需要处理,并且希望将它们分成两个线程,以便使用更多 CPU 更快地完成此任务。
我有一个名为PrepareTask的SwingWorker类,它有一个带有两个int的构造函数:
class PrepareTask extends SwingWorker<Void, Void> {
int start, end;
PrepareTask (int start, int end) { ... }
...
public Void doInBackground() {... }
public void done() { ... }
我创建了两个这样的实例:
PrepareTask prepareTask = new PrepareTask(0,numberOfFiles/2);
prepareTask.execute();
PrepareTask prepareTask2 = new PrepareTask(numberOfFiles/2, numberOfFiles);
prepareTask2.execute();
两个实例都已启动(它出现了),但是当它运行时,我可以看到(打印stmts)第一个准备必须完成(在第二个开始之前打印 stmts 。而且CPU利用率和以前一样,大约是30%。当然,它们都从同一源(DefaultTableModel)获取数据。
关于如何做到这一点或我做错了什么有什么想法吗? 谢谢。
My computer has 4 cores and I am running a Java swing gui program. When I run my application it only uses two cores and about 30% CPU utilization. I have a large number of files to process and want to split them up into two threads to get this task done faster using more cpu.
I have a SwingWorker class called PrepareTask, that has a constructor with two ints:
class PrepareTask extends SwingWorker<Void, Void> {
int start, end;
PrepareTask (int start, int end) { ... }
...
public Void doInBackground() {... }
public void done() { ... }
I create two instances of this like:
PrepareTask prepareTask = new PrepareTask(0,numberOfFiles/2);
prepareTask.execute();
PrepareTask prepareTask2 = new PrepareTask(numberOfFiles/2, numberOfFiles);
prepareTask2.execute();
Both are launched (it appears) but when it runs I can see (print stmts) that the first prepare has to finish (print stmts inside) before the second one starts. And the CPU utilization is the same as before, about 30%. They both of course grab data from the same source, a DefaultTableModel.
Any ideas on how to do this or what I am doing wrong?
thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是 SwingWorker 行为从一个 Java 6 更新更改为另一个 Java 6 更新的结果。实际上,在 Java 6 的旧 SUN 错误数据库中有一个关于它的错误报告。
发生的情况是 SUN 将原始 SwingWorker 实现从使用 N 个线程更改为使用 1 个线程和无界队列。因此,您不能再让两个 SwingWorker 同时运行。 (这也会造成可能发生死锁的情况:如果一个 Swingworker 等待另一个等待第一个的 Swingworker,则一个任务可能会因此进入死锁。)
您可以做的就是使用 ExecutorService 并在其上发布 FutureTasks 来解决这个问题 。它。这些将提供 99% 的 SwingWorker API(SwingWorker 是 FutureTask 的衍生品),您所要做的就是正确设置您的 Executor。
This is the result of a change in SwingWorker behaviour from one Java 6 update to another. There's actually a bug report about it in the old SUN bug database for Java 6.
What happened was SUN changed the original SwingWorker implementation from using N threads, to using 1 thread with an unbounded queue. Therefore you cannot have two SwingWorkers run concurrently anymore. (This also creates a scenario where deadlock may occur: if one swingworker waits for another which waits for the first, one task might enter a deadlock as a result.)
What you can do to get around this is use an ExecutorService and post FutureTasks on it. These will provide 99% of the SwingWorker API (SwingWorker is a FutureTask derivative), all you have to do is set up your Executor properly.
也许 Swing 正在控制线程的调度?或者也许 SwingWorker 的线程池大小为 1(SwingWorker javadoc 中没有关于运行多个 SwingWorker 线程的描述,我猜多个线程可能会导致 Swing 中出现一些困难的并发问题)。
如果您只想并行运行一些处理,
你能通过扩展来解决这个简单的方法吗
Java
Thread
类,实现run
,调用SwingUtilities.invokeLater()
at更新 GUI 的任何更改的结束:
启动线程:
或者您的数据模型中的某些内容可能是单线程的并阻塞第二个线程?
在这种情况下,您必须使用数据模型来解决该问题。
Maybe Swing is controlling the scheduling of your threads? Or maybe SwingWorker has a thread pool size of 1 (there is no description in SwingWorker javadoc about running multiple SwingWorker threads and I guess multiple threads could cause some difficult concurrency problems in Swing).
If all you want to do is run some processing in parallel,
can you solve this the simple way by extending the
Java
Thread
class, implementingrun
, callingSwingUtilities.invokeLater()
atthe end to update the GUI with any changes:
start the threads with:
Or maybe something in your data model is single-threaded and blocking the second thread?
In that case, you have to solve that problem with the data model.