2014-04-30 28 views
2

我正在根据我需要建立的多个连接生成SwingWorkers。我试图让我设置一个固定数量的最大并发SwingWorkers,当其中一个完成另一个启动时(或许多其他启动时,如果很多完成)。基于http://java.dzone.com/articles/multi-threading-java-swing我设立基本的SwingWorker这样的:
如何正确使用ExecutorService来管理并发运行的SwingWorkers的数量?

SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() { 
     @Override 
     protected Boolean doInBackground() throws Exception { 

         System.out.println("One SwingWorker just ran! "); 
       } 

       return true; 
     } 

     // Can safely update the GUI from this method. 
     protected void done() { 

       boolean status; 
       try { 
         // Retrieve the return value of doInBackground. 
         status = get(); 
         statusLabel.setText("Completed with status: " + status); 
       } catch (InterruptedException e) { 
       // This is thrown if the thread's interrupted. 
       } catch (ExecutionException e) { 
       // This is thrown if we throw an exception 
       // from doInBackground. 
       } 
     } 


}; 

worker.execute(); 


现在,我在如何实现我上述的机制不确定。

https://stackoverflow.com/a/8356896/988591我看到了,我可以用一个ExecutorService执行SwingWorker类的实例,这个接口还允许设置线程数:

int n = 20; // Maximum number of threads 
ExecutorService threadPool = Executors.newFixedThreadPool(n); 
SwingWorker w; //don*t forget to initialize 
threadPool.submit(w); 

我觉得这是我需要的,但我不不知道如何把整个事情放在一起(我对Java也很陌生)。有人可以在实施这个过程中指导我一点吗?说顶部我有int totalTask = 100;也许这只是一个循环的问题,但我似乎无法找到任何真正易于遵循的例子,我不能完全包围我的思想围绕它,所以..我会感谢一些帮助!谢谢。


更新:我已经设置了ExecutorService的是这样的:

ExecutorService executorService = Executors.newFixedThreadPool(500); 

for (int i = 0; i < 20 ; i++) { 

    executorService.submit(worker); 
    //I tried both... 
    //executorService.execute(worker); 
} 


与我已删除worker.execute()叫做SwingWorker的后上方,但从控制台输出仅仅是一个单一的“一个SwingWorker刚跑过!“一行,那是怎么回事?我做错了什么?

+0

正如我在您之前的问题中注意到的,SwingWorkers实例的数量正在稳定运行,SwingWorker从Future初始化,并且无法保证每个实例在同一时间结束或者另一个实例已启动(对于使用Thread的逻辑也是有效的,但没有错误),带有Runnable的逻辑#Thead更好,更容易和更舒适,get()完成()用于捕获可能的异常,而不是返回 – mKorbel

+0

我对他们在此完成的次序不感兴趣案件。不确定你的意思是“没有错误”。在我为SwingWorker done()和get()读取的所有文档中,它们分别用于发出回调方法,该方法1)可以访问SwingWorker doInBackground()的返回值,以及2)可以安全地更新GUI(因为它是自动的在美国东部时间推出)。我不确定是否引用其他get()和done()方法,但我不知道它们是否也用于Runnable#Thread。 –

+0

1.你可以[获取()一个异常或返回](发布时间:15年07月01日原作者: )/ setProcess – mKorbel

回答

0

那一刻当你想到:这是如此明显!

ExecutorService executorService = Executors.newFixedThreadPool(20); 

for (int i = 0; i < 500; i++) { 

     SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() { 
       @Override 
       protected Boolean doInBackground() throws Exception { 

         System.out.println("One SwingWorker just ran!"); 
         return true; 
       } 


       protected void done() { 

         boolean status; 
         try { 

           status = get(); 

         } catch (InterruptedException e) { 
         // This is thrown if the thread's interrupted. 
         } catch (ExecutionException e) { 
         // This is thrown if we throw an exception 
         // from doInBackground. 
         } 
       } 

     }; 


     executorService.submit(worker); 
} 


它的伟大工程!

0

请看看SwingWorker的源代码。 可以类似的东西,以execute()方法

public final void execute() { 
    getWorkersExecutorService().execute(this); 
} 

在这一点上,你可以创建一个的ExecutorService和管理池

SwingWorker<Boolean, Void> test = new SwingWorker<Boolean, Void>() { 
     private ExecutorService service = new ThreadPoolExecutor(5, 10, 
       10L, TimeUnit.MINUTES, 
       new LinkedBlockingQueue<Runnable>(), 
       new ThreadFactory() { 
        AtomicInteger count= new AtomicInteger(); 
        @Override 
        public Thread newThread(Runnable r) { 
         return new Thread("Pooled SwingWorker " + count.getAndAdd(1)); 
        } 
       }); 
     @Override 
     protected Boolean doInBackground() throws Exception { 
      return true; 
     } 

     public void doIt() { 
      service.execute(this); 
     } 

    }; 
1

你会做这样的事情:

  • 如显示 所示,使用固定的threadPool启动executorservice。
  • 在循环中创建您的可运行。尽可能多的可运行的,你需要的。
  • 您可以有50个线程和5000个可运行的程序。在可运行的第一个可用的线程之后,无论哪个线程都是空闲的将会接收到第51个任务,并且如此等等。
  • 用你的Runnable调用executorservice的execute方法。
  • 一旦完成,就关闭执行程序服务。

像这样:

ExecutorService executorService = Executors.newFixedThreadPool(500); 

for (long i = 0; i < 1000000; i++) { 
    Runnable populator = new YourRunnable(); 
    executorService.execute(populator); 
} 
executorService.shutdown(); 
while(!executorService.isTerminated()){ 
} 

这isTerminated可以用来检查executorServices是否真的下降。由于即使在调用shutdown()方法(因为它们还没有完成任务)之后,您可以运行多个执行程序线程,while循环的行为就像是等待调用。

而一个关键的问题是:无论您想传递给ExecutorService,它都必须是Runnable实现。在你的情况下,你的SwingWorker必须是一个Runnable。

+0

所以..呃..如何使SwingWorker成为Runnable? –

+0

我不应该这样做,但有点谷歌搜索返回给我这个:http://greatratrace.blogspot.in/2010/01/throttling-swingworker-using.html。您可以根据自己的需要进行调整。 – prabugp

+0

我之前实际上曾经访问过那个页面,但由于布局糟糕,我关闭了它。感谢让我重新考虑它。 –

1

这很有趣。使用具有有限池的ExecutorService时,只需要随时提交工作人员,并且只需同时执行该数量的工作人员。

我做了这个小测试应用程序,您可以按按钮提交一些工作人员,只要您想要的速度一样快,您可以看到在任何给定时间执行的工作人员数量永远不会高于值numberOfThreads您使用初始化ExecutorService。

import java.awt.BorderLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 

import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JTextArea; 
import javax.swing.SwingUtilities; 
import javax.swing.SwingWorker; 

public class SwingWorkerExecutorTest 
{ 
    public static void main(String[] args) 
    { 
     SwingUtilities.invokeLater(new Runnable() 
     { 
      @Override 
      public void run() 
      { 
       new SwingWorkerExecutorTest(); 
      } 
     }); 
    } 


    public SwingWorkerExecutorTest() 
    { 
     JFrame frame = new JFrame("Frame"); 

     int numberOfThreads = 2; //1 so they are executed one after the other. 
     final ExecutorService threadPool = Executors.newFixedThreadPool(numberOfThreads); 

     JButton button1 = new JButton("Submit SwingWorker 1"); 
     button1.addActionListener(new ActionListener() 
     { 
      @Override 
      public void actionPerformed(ActionEvent e) 
      { 
       String workerName = "Worker 1"; 
       appendMessage("Submited " + workerName); 
       SwingWorker worker = new TestWorker(workerName); 
       threadPool.submit(worker); 
      } 
     }); 

     JButton button2 = new JButton("Submit SwingWorker 2"); 
     button2.addActionListener(new ActionListener() 
     { 
      @Override 
      public void actionPerformed(ActionEvent e) 
      { 
       String workerName = "Worker 2"; 
       appendMessage("Submited " + workerName); 
       SwingWorker worker = new TestWorker(workerName); 
       threadPool.submit(worker); 
      } 
     }); 

     JButton button3 = new JButton("Submit SwingWorker 3"); 
     button3.addActionListener(new ActionListener() 
     { 
      @Override 
      public void actionPerformed(ActionEvent e) 
      { 
       String workerName = "Worker 3"; 
       appendMessage("Submited " + workerName); 
       SwingWorker worker = new TestWorker(workerName); 
       threadPool.submit(worker); 
      } 
     }); 

     JPanel buttonsPanel = new JPanel(); 
     buttonsPanel.add(button1); 
     buttonsPanel.add(button2); 
     buttonsPanel.add(button3); 
     frame.add(buttonsPanel, BorderLayout.PAGE_END); 

     _textArea = new JTextArea("Submit some workers:\n"); 
     _textArea.setEditable(false); 
     frame.add(new JScrollPane(_textArea)); 

     frame.setSize(600, 400); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 


    private class TestWorker extends SwingWorker 
    { 
     public TestWorker(String name) 
     { 
      _name = name; 
     } 

     @Override 
     protected Object doInBackground() throws Exception 
     { 
      String message = "A " + _name + " has started!"; 
      appendMessage(message); 
      doHardWork(); 
      return null; 
     } 

     @Override 
     protected void done() 
     { 
      String message = "A " + _name + " has finished!"; 
      appendMessage(message); 
     } 

     private void doHardWork() 
     { 
      try 
      { 
       Thread.sleep(2000); 
      } 
      catch (InterruptedException e) 
      { 
       e.printStackTrace(); 
      } 
     } 

     private String _name; 
    } 

    private static void appendMessage(String message) 
    { 
     _textArea.append(message + "\n"); 
     System.out.println(message); 
    } 

    private static JTextArea _textArea; 
} 

它看起来像这样:

example

例如,一些2线程,你会怎么本身如果提交了很多工人就在同一时间需要2和执行它们。

相关问题