[英]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.