繁体   English   中英

Java中的线程等待列表

[英]Waiting list of threads in java

我正在用HttpClient编写一个swing应用程序,并且需要一种下载列表的方法,因为在开始新的下载之前,我需要等待1分钟(例如)。

因此,我想创建一个线程等待列表(下载)。 我会有一个带有时间参数并包含线程列表的类,当我在列表中添加线程时,如果没有正在运行的线程,它将开始。 否则,它等待轮到它。

有什么工具可以做到这一点吗?

非常感谢你的帮助。

是。 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分钟内启动。 并解决您的最后一点。 如果在1分钟后当前有正在下载的任务(此配置意味着要下载10个任务),则可运行的提交将不得不等待,直到其他下载之一完成。

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

编辑:我将保留上一个答案,但使用解决方案对其进行更新,以提交任务以在上一个任务完成后1分钟恰好开始。 您将使用两个ExecutorServices。 一个提交给被规避的执行人,另一个执行定时执行。 最后,第一个执行程序将等待完成,并继续排​​队等待其他任务。

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分钟(即使没有其他任务提交)时,此方法才起作用。

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

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

ExecutorService executor = Executors.newFixedThreadPool(1);

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

Java并发包包含用于执行您所要求的类的类。 您正在谈论的一般构造是由ThreadPool支持的Executor 您将生成可运行项列表,并将其发送给执行程序。 执行程序后面有一个线程池,当线程可用时,它将运行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);
  }

这可能不是最好的解决方案,但是由于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);
        }

    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM