2009-08-27 79 views
4

我有一個小圖像處理應用程序,它使用SwingWorker一次完成多件事情。但是,如果我運行以下代碼(過於簡化的摘錄),它只會掛在JDK 7 b70(窗口)上,但在6u16中運行。它會在另一個工作人員中啓動一個新工作人員並等待其結果(真實應用程序運行多個子工作人員並等待所有這些)。我是否在這裏使用了一些錯誤的模式(因爲大多數人在3-5人的迴轉工作者池中,我認爲它的限制是10)?JDK-7 SwingWorker死鎖?

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(); 
         } 
       }); 
     } 

} 
+0

您是否試圖獲得堆棧轉儲? – 2009-08-27 16:51:43

+0

它似乎掛在sw2.get(),並且在jdk7中只有一個swingworker命名的線程。在jdk6上,我立刻看到了3-5。 – akarnokd 2009-08-27 16:53:21

回答

0

望着用於SwingWorker的源代碼,它看起來像一個ExecutorService被用作工作線程池。這有可能是使用的ExecutorService的類型有Java 6中和Java 7之間改變它看起來像如果ExecutorService的一次只管理正是1線程代碼就會死鎖(你似乎已經注意到了)。

這是因爲你的'sw2.get()調用將阻止當前線程,這是相同的線程SW2將嘗試使用。 sw2永遠不會執行,因爲第一名工作人員正在阻止。

我認爲最好的辦法是改變你的邏輯,這樣你不叫這樣的搖擺工人鏈。

+0

嗯,它聽起來沒有兼容性 - 如果我有多個swingworkers執行,它們將始終按照JDK 7順序運行(不管多核cpu)?我想我必須將外部的迴轉工具變成正常的螺紋線。 – akarnokd 2009-08-27 16:59:39

1

你SwingWorkers在你的SwingWorker線程中執行。所以當你看到

它似乎掛在sw2.get()並且在jdk7中只有一個swingworker命名的線程。在jdk6上,我立刻看到了3-5。 - kd304

這是因爲SwingWorker類並不是一個線程,但任務要在線程中運行,並在Java 6的ExecutorService的SwingWorker的默認配置是在Java 7中配置不同從一個。您的SwingWorkerExecutorService(在SwingWorker類中定義)的IE對於分配給任務的最大線程數具有不同的值。

//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) 
} 

你只有一個線程運行的SwingWorker任務和第一任務正在等待第二個任務,不能運行的完成,因爲線程的第二個任務將是上運行等待第二項任務完成後才能返回。在依賴於另一個執行的swingworker線程上製作死鎖肯定是一條路徑。您可能想要查看使用ExecutorService來安排要在SwingWorker線程上運行的事件,並且不要讓一個計劃的事件依賴於另一個計劃的事件的完成。

Java 7 SwingWorker

+0

公平的解釋,但爲什麼行爲改變了?我希望在JDK 7中看到3個swingworker-線程?那麼最初的多線程swignworker執行是否是bug? – akarnokd 2009-08-27 21:18:23

-1

JDK更新18之前,你可以運行:

public static void main(String[] args) { 

    new SwingWorker<Void, Void>() { 
     @Override 
     protected Void doInBackground() throws Exception { 
      System.out.println("ok"); 
      return null; 
     } 
    }.execute(); 

} 

這個代碼不工作了,只是因爲SwingWorkers必須在美國東部時間執行。

因此,你不能嵌套SwingWorkers(SW2絕不會運行在新的JDK示例代碼)。

我想用的ExecutorService java.util.concurrent.Future代替嵌套調用swingWorkers是一個很好的解決方法。

+2

SwingWorkers不一定必須在EDT上執行。實際上,SwingWorker Javadoc明確提到了SwingWorker產生的「當前線程」,並沒有說明它必須是Event Dispatch Thread。 – Trejkaz 2010-05-04 01:22:31