JDK-7 SwingWorker Deadlocks?

I have a small image processing application that uses several things at the same time using SwingWorker. However, if I run the following code (simplified shutter speed), it just hangs on JDK 7 b70 (windows), but works in 6u16. He starts a new employee inside another employee and waits for his result (the real application launches several subordinates and waits for all this). Did I use some wrong patterns here (as a rule, in the swingworker-pool there are 3-5 workers who have a limit of 10)?

import javax.swing.SwingUtilities; import javax.swing.SwingWorker; public class Swing { static SwingWorker<String, Void> getWorker2() { return new SwingWorker<String, Void>() { @Override protected String doInBackground() throws Exception { return "Hello World"; } }; } static void runWorker() { SwingWorker<String, Void> worker = new SwingWorker<String, Void>() { @Override protected String doInBackground() throws Exception { SwingWorker<String, Void> sw2 = getWorker2(); sw2.execute(); return sw2.get(); } }; worker.execute(); try { System.out.println(worker.get()); } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { runWorker(); } }); } } 
+4
source share
4 answers

Since no one has fired the link yet, it looks like this is actually a known bug:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6880336

Surprisingly, less than 100 votes for what should be a showstopper bug for most non-trivial applications.

+6
source

Your SwingWorkers run in your SwingWorker thread. Therefore when you see

It seems to hang on sw2.get (), and in jdk7 there is only one thread named swingworker. On jdk6, I see 3-5 at the same time. - kd304

This is because the SwingWorker class is not a thread, and the task to be performed on the thread, and the default configuration for the ExecutorService for SwingWorker in Java 6 is different from what it was in Java 7. IE your SwingWorkerExecutorService (which is defined inside the class SwingWorker) has a different meaning for the maximum number of threads for task distribution.

 //From Java 6 SwingWorker private static final int MAX_WORKER_THREADS = 10; public final void execute() { getWorkersExecutorService().execute(this); } private static synchronized ExecutorService getWorkersExecutorService() { ... private static synchronized ExecutorService getWorkersExecutorService() { new ThreadPoolExecutor(0, MAX_WORKER_THREADS, 1L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), threadFactory) } 

You have only one thread on which SwingWorker tasks are running, and this first task is waiting for the completion of the second task, which cannot be started, since the thread on which the second task will be executed, waits for the second before it returns. The execution on a swingworker thread depends on the execution of another - the right way to a dead end. You can see how to use the ExecutorService to schedule events that will be executed in the SwingWorker thread, and not execute one scheduled event depending on another scheduled event completion.

Java 7 SwingWorker

+1
source

Looking at the source code of SwingWorker, it looks like ExecutorService is used as a pool of workflows. It is possible that the type of ExecutorService used has changed between Java 6 and Java 7. It looks like your code will slow down if the ExecutorService manages exactly 1 thread at a time (as you seem to notice).

This is because your call to "sw2.get ()" blocks the current thread, which is the same thread that sw2 will try to use. sw2 can never be executed because the first worker is blocked.

I think the best solution is to change your logic so that you don't call Swing worker chains as follows.

0
source

Before updating the 18 JDK, you can run:

 public static void main(String[] args) { new SwingWorker<Void, Void>() { @Override protected Void doInBackground() throws Exception { System.out.println("ok"); return null; } }.execute(); } 

This code no longer works, simply because SwingWorkers needs to be run on EDT.

Therefore, you cannot embed SwingWorkers (sw2 will never run in your sample code in the new JDKs).

I assume that replacing nested swingWorkers with the executorService java.util.concurrent.Future function is a good workaround.

-1
source

All Articles