如何正确使用ExecutorService来管理同时运行的SwingWorkers的数量?

时间:2014-04-30 17:12:07

标签: java swing threadpool executorservice swingworker

我正在根据我需要建立的许多连接生成SwingWorkers。我试图做到这一点,以便我设置一个固定数量的最大的同意SwingWorkers,当其中一个完成另一个启动(或许多其他人启动,如果许多已完成)。基于http://java.dzone.com/articles/multi-threading-java-swing我正在设置基本的SwingWorker,如下所示:

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


我已经删除了上面的SwingWorker之后调用的worker.execute(),但是控制台的输出只是一个&#34; One SwingWorker刚刚运行!&#34; 行,这是怎么回事?我做错了什么?

4 个答案:

答案 0 :(得分:1)

您可以这样做:

  • 使用固定的threadPool启动执行程序服务 所示。
  • 在循环中创建您的runnable。尽可能多的runnables。
  • 您可以拥有50个线程和5000个可运行的线程。 1月50日之后 runnables,无论哪个线程是免费的,都会收到第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()){
}

thatTerminated可用于检查executorServices是否实际关闭。由于即使在调用shutdown()方法之后也可以运行多个执行程序线程(因为它们尚未完成任务),因此while循环就像一个等待调用。

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

答案 1 :(得分:1)

这很有意思。使用具有有限池的ExecutorService,您只需要随时提交工作人员,并且只会同时执行这些工作量。

我制作了这个小测试应用程序,您可以按下按钮提交一些工作人员,并且您可以查看在任何给定时间执行的工作量从不高于值{{1你使用。

初始化了ExecutorService
numberOfThreads

看起来像这样:

example

例如,如果您提交了大量工作人员,那么如果您提交了大量工作人员,那么如果您提交了大量工作人员,则需要一次执行2个工作线程。

答案 2 :(得分: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);
        }

    };

答案 3 :(得分: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);
}


它很棒!