Java ExecutorService中队列中的最大等待时间

Java ExecutorService中队列中的最大等待时间,java,multithreading,Java,Multithreading,有没有办法设置Executor服务的最大等待时间 例如,当您将两个while true runnable传递给SingleThreadExecutor时,第一个将永远工作,第二个将永远等待 我希望得到一个关于第二个Runnable的TimeOutException public static void main(String[] args) throws IOException { ExecutorService executor = Executors.newSingleThr

有没有办法设置Executor服务的最大等待时间

例如,当您将两个while true runnable传递给
SingleThreadExecutor
时,第一个将永远工作,第二个将永远等待

我希望得到一个关于第二个Runnable的TimeOutException

public static void main(String[] args) throws IOException {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 2; i++) {
            int finalI = i;
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    while (true) {
                        try {
                            System.out.println("#"+ finalI + " Runnable !");
                            Thread.sleep(1000);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            });
        }
    }
publicstaticvoidmain(字符串[]args)引发IOException{
ExecutorService executor=Executors.newSingleThreadExecutor();
对于(int i=0;i<2;i++){
int finalI=i;
executor.execute(新的Runnable(){
@凌驾
公开募捐{
while(true){
试一试{
System.out.println(“#”+finalI+“Runnable!”);
睡眠(1000);
}捕获(例外e){
e、 printStackTrace();
}
}
}
});
}
}

您的执行器只有一个线程。它将在内部对不同的可运行任务进行排队,并尝试逐个完成它们。如果第一个任务从未完成(因为这是一个while-true循环),那么第二个任务将永远不会启动

您可以使用
submit
而不是
execute
来获取未来的对象,并执行带有超时的
get
操作

public static void main(String[] args) throws IOException {
    ExecutorService executor = Executors.newSingleThreadExecutor();
    List<Future> future = new ArrayList<>();
    for (int i = 0; i < 2; i++) {
        int finalI = i;
        future.add(executor.submit(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        System.out.println("#"+ finalI + " Runnable !");
                        Thread.sleep(1000);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }));
    }
    // Check if second task finishes in the next 2 seconds, and throw a TimeoutException if it does not

    try {
        future.get(1).get(2000, TimeUnit.MILLISECONDS);
    } catch (TimeoutException e) {
        e.printStackTrace();
    }
}

如果所有线程都忙,此Executor服务将自动拒绝任务

您的执行器只有一个线程。它将在内部对不同的可运行任务进行排队,并尝试逐个完成它们。如果第一个任务从未完成(因为这是一个while-true循环),那么第二个任务将永远不会启动

您可以使用
submit
而不是
execute
来获取未来的对象,并执行带有超时的
get
操作

public static void main(String[] args) throws IOException {
    ExecutorService executor = Executors.newSingleThreadExecutor();
    List<Future> future = new ArrayList<>();
    for (int i = 0; i < 2; i++) {
        int finalI = i;
        future.add(executor.submit(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        System.out.println("#"+ finalI + " Runnable !");
                        Thread.sleep(1000);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }));
    }
    // Check if second task finishes in the next 2 seconds, and throw a TimeoutException if it does not

    try {
        future.get(1).get(2000, TimeUnit.MILLISECONDS);
    } catch (TimeoutException e) {
        e.printStackTrace();
    }
}
如果所有线程都忙,此Executor服务将自动拒绝任务

有没有办法设置Executor服务的最大等待时间

如果您谈论的是等待作业开始运行,那么答案很不幸是“不容易”。有一些方法可以使用
ThreadPoolExecutor
中的队列来完成,但它们会被视为黑客,不推荐使用。您还可以扩展
ThreadPoolExecutor
,但这可能会变得复杂

一个[更好的]解决方案是从外部管理队列

// synchronous queue waits for someone to take() from the queue before returning
final BlockingQueue<Runnable> jobQueue = new SynchronousQueue<Runnable>();
...
// submit all of your threads who get jobs from your queue to run
executor.execute(new Runnable() {
    @Override
    public void run() {
         while (!Thread.currentThread.isInterrupted()) {
              try {
                  Runnable job = jobQueue.take();
                  job.run();
              } catch (InterruptedException ie) {
                  // always recommended
                  Thread.currentThread().interrupt();
                  return;
              }
         }
    }
});
...
// now we can try to add a job into the queue but if it is full, offer may timeout
if (!queue.offer(new Runnable() { ... }, 2000, TimeUnit.SECONDS)) {
    // timed out
}
//同步队列在返回之前等待有人从队列中取出()
final BlockingQueue jobQueue=new SynchronousQueue();
...
//提交从队列中获取作业的所有线程以运行
executor.execute(新的Runnable(){
@凌驾
公开募捐{
而(!Thread.currentThread.isInterrupted()){
试一试{
Runnable job=jobQueue.take();
job.run();
}捕获(中断异常ie){
//一直推荐
Thread.currentThread().interrupt();
返回;
}
}
}
});
...
//现在我们可以尝试将作业添加到队列中,但如果作业已满,则可能会超时
if(!queue.offer(new Runnable(){…},2000,TimeUnit.SECONDS)){
//超时
}
希望这有帮助

有没有办法设置Executor服务的最大等待时间

如果您谈论的是等待作业开始运行,那么答案很不幸是“不容易”。有一些方法可以使用
ThreadPoolExecutor
中的队列来完成,但它们会被视为黑客,不推荐使用。您还可以扩展
ThreadPoolExecutor
,但这可能会变得复杂

一个[更好的]解决方案是从外部管理队列

// synchronous queue waits for someone to take() from the queue before returning
final BlockingQueue<Runnable> jobQueue = new SynchronousQueue<Runnable>();
...
// submit all of your threads who get jobs from your queue to run
executor.execute(new Runnable() {
    @Override
    public void run() {
         while (!Thread.currentThread.isInterrupted()) {
              try {
                  Runnable job = jobQueue.take();
                  job.run();
              } catch (InterruptedException ie) {
                  // always recommended
                  Thread.currentThread().interrupt();
                  return;
              }
         }
    }
});
...
// now we can try to add a job into the queue but if it is full, offer may timeout
if (!queue.offer(new Runnable() { ... }, 2000, TimeUnit.SECONDS)) {
    // timed out
}
//同步队列在返回之前等待有人从队列中取出()
final BlockingQueue jobQueue=new SynchronousQueue();
...
//提交从队列中获取作业的所有线程以运行
executor.execute(新的Runnable(){
@凌驾
公开募捐{
而(!Thread.currentThread.isInterrupted()){
试一试{
Runnable job=jobQueue.take();
job.run();
}捕获(中断异常ie){
//一直推荐
Thread.currentThread().interrupt();
返回;
}
}
}
});
...
//现在我们可以尝试将作业添加到队列中,但如果作业已满,则可能会超时
if(!queue.offer(new Runnable(){…},2000,TimeUnit.SECONDS)){
//超时
}

希望这有帮助。

我也知道;),但是得到一个TimeOutException呢?!不会有超时。但是,您可以使用
submit
而不是
execute
来接收未来。然后您可以执行
future.get(1000,TimeUnit.MILLSECONDS)
,如果任务的执行没有按时完成,它将抛出TimeoutException。我可以扩展我的答案来展示一些实现这种行为的代码:)如果您能给我展示一个有用的示例代码,我将不胜感激。
future.get()
等待作业完成。它不会阻止提交作业。在使用
服务时,您仍然必须阻止主线程等待答复,以查看线程池是否繁忙(类似于我的future.get()检查)。唯一的区别是,在我的例子中,你实际提交了工作,并检查了它的状态,在@Gray的回答中,你检查了你是否可以提交工作。我猜一切都将取决于您的应用程序架构,如果您想在发送任务后立即阻止,@Gray的回答应该更好。如果您想执行其他逻辑并稍后检查任务是否完成,我的方法应该会执行得更好。我也知道;),但是得到一个TimeOutException呢?!不会有超时。但是,你可以