等待java中的线程列表

时间:2012-01-05 18:27:42

标签: java multithreading

我正在使用HttpClient编写一个swing应用程序,我需要一种方法来制作下载列表,因为我需要等待1分钟(例如)才能开始新的下载。

所以我想创建一个等待的线程列表(下载)。 我有一个类,它接受一个时间参数,并包含一个线程列表,当我在列表中添加一个线程时,如果没有正在运行的线程,它就会启动。否则它等待转弯。

有没有工具可以做到这一点?

非常感谢你的帮助。

5 个答案:

答案 0 :(得分:3)

是。 ScheduledExecutorService。您可以通过Executors.newScheduledThreadPool(corePoolSize)创建固定长度的服务。当您准备好提交任务以等待一段时间后,只需将其提交到ScheduledExecutorService.schedule

ScheduledExecutorService e = Executors.newScheduledThreadPool(10)
private final long defaultWaitTimeInMinutes = 1;
public void submitTaskToWait(Runnable r){
    e.schedule(r, defaultWaitTimeInMinutes, TimeUnit.MINUTES);
}

此处任务将在提交后1分钟内启动。并解决你的最后一点。如果当前正在下载任务(此配置意味着下载了10个任务),则在1分钟结束后,提交的可运行程序将必须等到其他下载完成之一。

请记住,这与您设计它的方式略有不同。对于每个新任务,您都不会创建新线程,而是提交给已经有线程等待的服务。例如,如果您只想一次下载一个任务,则从Executors.newScheduledThreadPool(10)更改为Executors.newScheduledThreadPool(1)

编辑:我将留下我之前的答案,但使用解决方案更新它,以便在上一个任务完成后的1分钟内提交任务。您将使用两个ExecutorServices。一个提交给计划的Executor,另一个提交定时执行。最后,第一个Executor将等待完成并继续排队的其他任务。

ExecutorService e = Executors.newSingleThreadExecutor();
ScheduledExecutorService scheduledService = Executors.newScheduledThreadPool(1)
public void submitTask(final Runnable r){
    e.submit(new Runnable(){
       public void run(){
           ScheduledFuture<?> future= scheduledService.schedule(r, defaultWaitTimeInMinutes, TimeUnit.MINUTES);
           future.get(); 

       }
    });
}

现在当future.get();完成通过submitTask提交的下一个Runnable将运行,然后安排一分钟。最后,只有当您要求任务等待1分钟时,即使没有提交其他任务,这也会有效。

答案 1 :(得分:1)

我认为这是解决问题的错误方法。更合乎逻辑的方法是创建将添加到作业队列的“下载作业”对象。创建一个TimerTask,每隔1分钟查询一次“队列”,选择Runnable / Callable个工作并将其提交到ExecutorService

答案 2 :(得分:0)

您可以使用内置ExecutorService。您可以将任务排队为Runnable,它们将在可用线程上运行。如果您希望一次只运行一个任务,请使用newFixedThreadPool(1);

ExecutorService executor = Executors.newFixedThreadPool(1);

然后,您可以在每个Thread.sleep Runnable方法的开头添加一个人工run,以确保它在开始之前等待必要的时间(不是最优雅的选择,我知道)。

答案 3 :(得分:0)

Java Concurrency package包含用于执行您所要求的内容的类。您正在谈论的一般构造是Executor,它由ThreadPool支持。您生成一个Runables列表并将它们发送给Executor。 Executor后面有一个ThreadPool,它将在线程可用时运行Runnables。

以此为例,您可以拥有Runnable之类的内容:

  private static class Downloader implements Runnable {

    private String file;

    public Downloader(String file) {
      this.file = file;
    }

    @Override
    public void run() {
      // Use HttpClient to download file.
    }
  }

然后您可以通过创建Downloader对象并将其提交给ExecutorService来使用它:

  public static void main(String[] args) throws Exception {
    ExecutorService executorService = Executors.newFixedThreadPool(5);
    for (String file : args) {
      executorService.submit(new Downloader(file));
    }
    executorService.awaitTermination(100, TimeUnit.SECONDS);
  }

答案 4 :(得分:0)

这可能不是最好的解决方案,但是由于John Vint的回答,这就是我想出来的。我希望它会帮助别人。

package tests;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;


public class RunnableQueue 
{
    private long waitTime;
    private TimeUnit unit;

    ExecutorService e;

    public RunnableQueue(long waitTime, TimeUnit unit) {
        e = Executors.newSingleThreadExecutor();

        this.waitTime = waitTime;
        this.unit = unit;
    }

    public void submitTask(final Runnable r){
        e.submit(new Runnable(){
           public void run(){
               Thread t = new Thread(r);
               t.start();

               try {
                t.join();
                Thread.sleep(unit.toMillis(waitTime));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
           }
        });
    }

    public static void main(String[] args) {
        RunnableQueue runQueue = new RunnableQueue(3, TimeUnit.SECONDS);

        for(int i=1; i<11; i++)
        {
            runQueue.submitTask(new DownloadTask(i));
            System.out.println("Submitted task " + i);
        }

    }
}