2014-04-30 2 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; Возможно, это всего лишь вопрос некоторых циклов, но я не могу найти каких-либо действительно простых примеров, и я просто не могу полностью обдумать его, но так .. Я бы оцените некоторую помощь! Благодарю.


UPDATE: Я настроил 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 инициализируется из Будущего, и ничто не гарантирует, что все экземпляры завершены в одно и то же время или будет запущен другой экземпляр (действителен для логики с Thread тоже , но без ошибок), логики с Runnable # Thead лучше, проще и удобнее, get() in done() использовать для catch для возможного исключения, а не для возвратов – mKorbel

+0

Меня не интересует порядок, который они заканчивают в этом дело. Не уверен, что вы имеете в виду, «но без ошибок». Во всей документации, которую я прочитал для SwingWorker done() и get(), они используются соответственно для вызова метода обратного вызова, который 1) может получить доступ к возвращаемому значению SwingWorker doInBackground() и 2), может безопасно обновлять GUI (поскольку он автоматически запущен в EDT). Я не уверен, ссылаетесь ли вы на другие методы get() и done(), и я не знаю, если они также используются в Runnable # Thread. –

+0

1. вы можете [get() исключить или вернуть] (http://stackoverflow.com/questions/7053865/cant-get-arrayindexoutofboundsexception-from-future-and-swingworker-if-threa) 2. публиковать ()/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. Вы можете что-то подобное, чтобы выполнить() метод

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, как показано на рисунке .
  • В цикле создайте свой runnable. Как и многие другие.
  • У вас может быть 50 нитей и 5000 стоек. После 1-го 50
    стоков, в зависимости от того, какая нить свободна, она заберет 51-ю задачу и
    так далее.
  • Вызовите метод выполнения executorservice с помощью Runnable.
  • Как только все будет сделано, вы завершите работу службы-исполнителя.

Как это:

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

Итак .. uhm .. как сделать SwingWorker в Runnable? –

+0

Я не должен был этого делать, но немного Googling вернул мне это: 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 в то время, и выполняет их.

Смежные вопросы