【问题标题】:Java - Define a timeout for Callable within a ExecutorCompletionServiceJava - 在 ExecutorCompletionService 中为 Callable 定义超时
【发布时间】:2014-08-19 20:39:27
【问题描述】:

我在使用ExecutorCompletionService 时遇到了以下问题。我想在不同的线程中调用很多 Callable。这些 Callable 之间不共享任何信息。我需要为每个 Callable 定义一个超时,例如。运行时间不要超过 5 秒。每个 Callable 可以在我不知道何时开始的不同时间运行。超时后,应该停止/杀死线程,结果对我来说不再有趣。不应影响其他“正常”运行的线程。

因此,让我们以一个简单的可调用对象和我当前的 java 代码为例。

import java.util.Date;
import java.util.concurrent.Callable;

public class Job implements Callable<Integer> {

    int returnValue = 0;
    long millis = 0;

    public Job(long millis, int value) {
        this.millis = millis;
        this.returnValue = value;
    }

    @Override
    public Integer call() throws Exception, InterruptedException {
        try {
            System.out.println(new Date() + " " + returnValue + " started");
            Thread.sleep(millis);
            System.out.println(new Date() + " " + returnValue + " finished");
            return returnValue;
        } catch (InterruptedException e) {
            System.out.println(new Date() + " " + returnValue + " interrupted");
            throw e;
        }        
    }
}

以及使用 Callable 的另一个类。

import java.util.ArrayList;
import java.util.Date;
import java.util.concurrent.*;

public class CallableTest {

    public static void main(String[] args) {
        ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(2);
        CompletionService<Integer> pool = new ExecutorCompletionService<Integer>(newFixedThreadPool);
        
        for (int i = 10; i > 0; i--) {
            Job job = new Job(i * 1000, i);
            pool.submit(job);
        }
        
        ArrayList<Integer> results = new ArrayList<Integer>();
        for (int i = 1; i < 11; ++i) {
            try {
                Future<Integer> future = pool.take();
                Integer content = future.get(5, TimeUnit.SECONDS);
                results.add(content);
                System.out.println(new Date() + " added " + content);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (TimeoutException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        newFixedThreadPool.shutdownNow();

        System.out.println(new Date() + " results:");
        for (int j : results) {
            System.out.println(new Date() + " " + j);
        }
    }
}

输出类似于:

Sun Jun 29 08:01:00 CEST 2014 10 started
Sun Jun 29 08:01:00 CEST 2014 9 started
Sun Jun 29 08:01:09 CEST 2014 9 finished
Sun Jun 29 08:01:09 CEST 2014 added 9
Sun Jun 29 08:01:09 CEST 2014 8 started
Sun Jun 29 08:01:10 CEST 2014 10 finished
Sun Jun 29 08:01:10 CEST 2014 7 started
Sun Jun 29 08:01:10 CEST 2014 added 10
Sun Jun 29 08:01:17 CEST 2014 7 finished
Sun Jun 29 08:01:17 CEST 2014 6 started
Sun Jun 29 08:01:17 CEST 2014 added 7
Sun Jun 29 08:01:17 CEST 2014 8 finished
Sun Jun 29 08:01:17 CEST 2014 added 8
Sun Jun 29 08:01:17 CEST 2014 5 started
Sun Jun 29 08:01:22 CEST 2014 5 finished
Sun Jun 29 08:01:22 CEST 2014 added 5
Sun Jun 29 08:01:22 CEST 2014 4 started
Sun Jun 29 08:01:23 CEST 2014 6 finished
Sun Jun 29 08:01:23 CEST 2014 3 started
Sun Jun 29 08:01:23 CEST 2014 added 6
Sun Jun 29 08:01:26 CEST 2014 3 finished
Sun Jun 29 08:01:26 CEST 2014 2 started
Sun Jun 29 08:01:26 CEST 2014 added 3
Sun Jun 29 08:01:26 CEST 2014 4 finished
Sun Jun 29 08:01:26 CEST 2014 1 started
Sun Jun 29 08:01:26 CEST 2014 added 4
Sun Jun 29 08:01:27 CEST 2014 1 finished
Sun Jun 29 08:01:27 CEST 2014 added 1
Sun Jun 29 08:01:28 CEST 2014 2 finished
Sun Jun 29 08:01:28 CEST 2014 added 2
Sun Jun 29 08:01:28 CEST 2014 results:
Sun Jun 29 08:01:28 CEST 2014 9
Sun Jun 29 08:01:28 CEST 2014 10
Sun Jun 29 08:01:28 CEST 2014 7
Sun Jun 29 08:01:28 CEST 2014 8
Sun Jun 29 08:01:28 CEST 2014 5
Sun Jun 29 08:01:28 CEST 2014 6
Sun Jun 29 08:01:28 CEST 2014 3
Sun Jun 29 08:01:28 CEST 2014 4
Sun Jun 29 08:01:28 CEST 2014 1
Sun Jun 29 08:01:28 CEST 2014 2 

这不像我想要的那样工作。我希望每个运行时间超过 5 秒的 Callable 都应该被终止/结束/中断,并且只有运行时间低于 5 秒的 Callable 才能给我一个有效的结果。

我也试过没有 ExecutorCompletionService

public class CallableTest2 {
    public static void main(String[] args) {
        ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(2);
        List<Future<Integer>> futures = new ArrayList<Future<Integer>>();
        
        for (int i = 10; i > 0; i--) {
            Job job = new Job(i * 1000, i);
            futures.add(newFixedThreadPool.submit(job));
        }
        
        ArrayList<Integer> results = new ArrayList<Integer>();
        for (Future<Integer> future: futures) {
            try {
                Integer content = future.get(5, TimeUnit.SECONDS);
                results.add(content);
                System.out.println(new Date() + " added " + content);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (TimeoutException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        newFixedThreadPool.shutdownNow();

        System.out.println(new Date() + " results:");
        for (int j : results) {
            System.out.println(new Date() + " " + j);
        }
    }
}

有了结果:

Sun Jun 29 08:33:19 CEST 2014 9 started
Sun Jun 29 08:33:19 CEST 2014 10 started
java.util.concurrent.TimeoutException
    at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:228)
    at java.util.concurrent.FutureTask.get(FutureTask.java:91)
    at callabletest.CallableTest2.main(CallableTest2.java:29)
Sun Jun 29 08:33:28 CEST 2014 9 finished
Sun Jun 29 08:33:28 CEST 2014 8 started
Sun Jun 29 08:33:28 CEST 2014 added 9
Sun Jun 29 08:33:29 CEST 2014 10 finished
Sun Jun 29 08:33:29 CEST 2014 7 started
java.util.concurrent.TimeoutException
    at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:228)
    at java.util.concurrent.FutureTask.get(FutureTask.java:91)
    at callabletest.CallableTest2.main(CallableTest2.java:29)
Sun Jun 29 08:33:36 CEST 2014 7 finished
Sun Jun 29 08:33:36 CEST 2014 added 7
Sun Jun 29 08:33:36 CEST 2014 6 started
Sun Jun 29 08:33:36 CEST 2014 8 finished
Sun Jun 29 08:33:36 CEST 2014 5 started
java.util.concurrent.TimeoutException
    at java.util.concurrent.FutureTask$Sync.innerGet(Sun Jun 29 08:33:41 CEST 2014 5 finished
FutureTask.java:228)
Sun Jun 29 08:33:41 CEST 2014 added 5
    at java.util.concurrent.FutureTask.get(FutureTask.java:91)
Sun Jun 29 08:33:41 CEST 2014 4 started
    at callabletest.CallableTest2.main(CallableTest2.java:29)
Sun Jun 29 08:33:42 CEST 2014 6 finished
Sun Jun 29 08:33:42 CEST 2014 3 started
Sun Jun 29 08:33:45 CEST 2014 3 finished
Sun Jun 29 08:33:45 CEST 2014 2 started
Sun Jun 29 08:33:45 CEST 2014 4 finished
Sun Jun 29 08:33:45 CEST 2014 added 4
Sun Jun 29 08:33:45 CEST 2014 added 3
Sun Jun 29 08:33:45 CEST 2014 1 started
Sun Jun 29 08:33:46 CEST 2014 1 finished
Sun Jun 29 08:33:47 CEST 2014 2 finished
Sun Jun 29 08:33:47 CEST 2014 added 2
Sun Jun 29 08:33:47 CEST 2014 added 1
Sun Jun 29 08:33:47 CEST 2014 results:
Sun Jun 29 08:33:47 CEST 2014 9
Sun Jun 29 08:33:47 CEST 2014 7
Sun Jun 29 08:33:47 CEST 2014 5
Sun Jun 29 08:33:47 CEST 2014 4
Sun Jun 29 08:33:47 CEST 2014 3
Sun Jun 29 08:33:47 CEST 2014 2
Sun Jun 29 08:33:47 CEST 2014 1

现在我得到了一些 TimeoutExceptions,但也不是我期望的。例如。运行 9 和 7 秒的 Callable 不会抛出异常!

我必须在代码中进行哪些更改,以仅获取短运行线程的结果并终止长时间运行的线程。在示例中只有结果 1-5 而没有 6-10。

我已经测试了很多东西,但我无法让它发挥作用。 请帮忙


这是对使用 ScheduledExecutorService 的 bstar55 帖子的回答。

我将关于您的提示的代码更改为:

public class CallableTest3 {

    public static void main(String[] args) {
        ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);
        List<Future<Integer>> futures = new ArrayList<Future<Integer>>();
        
        for (int i = 10; i > 0; i--) {
            Job job = new Job(i * 1000, i);
            final Future handler = executor.submit(job);
            final int x = i;
            executor.schedule(new Runnable() {

                public void run() {
                    boolean cancel = handler.cancel(true);
                    if(cancel){
                        System.out.println(new Date() + " job " + x + " cancelled");
                    }else{
                        System.out.println(new Date() + " job " + x + " not cancelled");
                    }
                }
            }, 5000, TimeUnit.MILLISECONDS);
            futures.add(handler);
        }

        ArrayList<Integer> results = new ArrayList<Integer>();
        for (Future<Integer> future : futures) {
            try {
                Integer content = future.get(5, TimeUnit.SECONDS);
                results.add(content);
                System.out.println(new Date() + " added " + content);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (TimeoutException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        executor.shutdown();

        System.out.println(new Date() + " results:");
        for (int j : results) {
            System.out.println(new Date() + " --- " + j);
        }
    }
}

但这也不能按预期工作。 结果:

Sun Jun 29 10:27:41 CEST 2014 9 started
Sun Jun 29 10:27:41 CEST 2014 10 started
java.util.concurrent.TimeoutException
    at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:228)
    at java.util.concurrent.FutureTask.get(FutureTask.java:91)
    at callabletest.CallableTest3.main(CallableTest3.java:43)
Sun Jun 29 10:27:50 CEST 2014 9 finished
Sun Jun 29 10:27:50 CEST 2014 added 9
Sun Jun 29 10:27:50 CEST 2014 8 started
Sun Jun 29 10:27:51 CEST 2014 10 finished
Sun Jun 29 10:27:51 CEST 2014 7 started
java.util.concurrent.TimeoutException
    at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:228)
    at java.util.concurrent.FutureTask.get(FutureTask.java:91)
    at callabletest.CallableTest3.main(CallableTest3.java:43)
Sun Jun 29 10:27:58 CEST 2014 8 finished
Sun Jun 29 10:27:58 CEST 2014 6 started
Sun Jun 29 10:27:58 CEST 2014 7 finished
Sun Jun 29 10:27:58 CEST 2014 5 started
Sun Jun 29 10:27:58 CEST 2014 added 7
Sun Jun 29 10:28:03 CEST 2014 5 finished
Sun Jun 29 10:28:03 CEST 2014 4 started
java.util.concurrent.TimeoutException
    at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:228)
    at java.util.concurrent.FutureTask.get(FutureTask.java:91)
Sun Jun 29 10:28:03 CEST 2014 added 5
    at callabletest.CallableTest3.main(CallableTest3.java:43)
Sun Jun 29 10:28:04 CEST 2014 6 finished
Sun Jun 29 10:28:04 CEST 2014 3 started
Sun Jun 29 10:28:07 CEST 2014 3 finished
Sun Jun 29 10:28:07 CEST 2014 2 started
Sun Jun 29 10:28:07 CEST 2014 4 finished
Sun Jun 29 10:28:07 CEST 2014 added 4
Sun Jun 29 10:28:07 CEST 2014 added 3
Sun Jun 29 10:28:07 CEST 2014 1 started
java.util.concurrent.CancellationException
    at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:230)
    at java.util.concurrent.FutureTask.get(FutureTask.java:91)
    at callabletest.CallableTest3.main(CallableTest3.java:43)
Sun Jun 29 10:28:08 CEST 2014 1 finished
Sun Jun 29 10:28:08 CEST 2014 job 10 not cancelled
Sun Jun 29 10:28:08 CEST 2014 job 9 not cancelled
Sun Jun 29 10:28:08 CEST 2014 job 8 not cancelled
Sun Jun 29 10:28:08 CEST 2014 job 7 not cancelled
Sun Jun 29 10:28:08 CEST 2014 job 6 not cancelled
Sun Jun 29 10:28:08 CEST 2014 job 5 not cancelled
Sun Jun 29 10:28:08 CEST 2014 job 4 not cancelled
Sun Jun 29 10:28:08 CEST 2014 job 3 not cancelled
Sun Jun 29 10:28:08 CEST 2014 2 interrupted
Sun Jun 29 10:28:08 CEST 2014 job 1 not cancelled
Sun Jun 29 10:28:08 CEST 2014 added 1
Sun Jun 29 10:28:08 CEST 2014 results:
Sun Jun 29 10:28:08 CEST 2014 --- 9
Sun Jun 29 10:28:08 CEST 2014 --- 7
Sun Jun 29 10:28:08 CEST 2014 --- 5
Sun Jun 29 10:28:08 CEST 2014 --- 4
Sun Jun 29 10:28:08 CEST 2014 --- 3
Sun Jun 29 10:28:08 CEST 2014 --- 1
Sun Jun 29 10:28:08 CEST 2014 job 2 cancelled

但是工作 2 被取消了!


【问题讨论】:

  • 记录何时提交作业以及何时从池中获取作业。如果有兴趣查看在调用 future.get() 之前第一个作业已经运行了多长时间。
  • 好的,我想我开始明白发生了什么。您在两个线程上运行作业,然后尝试在单个线程上获得结果。在您等待一个结果的同时,至少还有一个其他作业正在运行,而您没有等待它。当您开始等待结果时,您等待的作业已经运行了一段时间,使您的 5 秒超时无效。

标签: java multithreading timeout executorservice callable


【解决方案1】:

我建议你把你的问题分成两个独立的:

  1. 在多个线程上运行
  2. 为每个操作使用超时

对于第一个(多线程),您已经使用了可以在 2 个线程上管理它的服务执行器:Executors.newFixedThreadPool(2)。如果您在此处应用超时,则超时适用于所有任务的运行,但您需要为每个作业设置超时。

对于超时问题,您可以通过一个类中每个作业的新服务执行器来管理它:JobManager。

package com.stackoverflow.q24473796;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class JobManager implements Callable<Integer> {

protected long timeout;
protected TimeUnit timeUnit;
protected Callable<Integer> job;

public JobManager(long timeout, TimeUnit timeUnit, Callable<Integer> job) {
this.timeout = timeout;
this.timeUnit = timeUnit;
this.job = job;
}

@Override
public Integer call() {
    Integer result = new Integer(-1); // default, this could be adapted
    ExecutorService exec = Executors.newSingleThreadExecutor();

    try {
        result = exec.submit(job).get(timeout, timeUnit);
    } catch (InterruptedException | ExecutionException | TimeoutException e) {
        // Whatever you want
        if (e instanceof TimeoutException) {
            System.out.println("Timeout get for " + job.toString());
        } else {
            System.out.println("exception get for " + job.toString() + " : " + e.getMessage());
        }

    }
    exec.shutdown();
    return result;
    }
}

然后,您可以从主线程调用任务,如下所示:

    Job job = new Job(i * 1000, i);
    Future<Integer> future = newFixedThreadPool.submit(new JobManager(5, TimeUnit.SECONDS, job));

我添加了您的 CallableTest: 包 com.stackoverflow.q24473796;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

public class CallableTest {

    public static void main(String[] args) {
        ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(2);

        List<Future<Integer>> futures = new ArrayList<Future<Integer>>();
        for (int i = 10; i > 0; i--) {
            Job job = new Job(i * 1000, i);
            Future<Integer> future = newFixedThreadPool.submit(new   JobManager(5, TimeUnit.SECONDS, job));
            futures.add(future);
        }

        ArrayList<Integer> results = new ArrayList<Integer>();
        for (Future<Integer> future : futures) {
            Integer result = new Integer(-1);
            try {
                result = future.get();
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
            if (result != -1) {
                results.add(result);
            }
        }

        newFixedThreadPool.shutdown();

        try {
            newFixedThreadPool.awaitTermination(60, TimeUnit.SECONDS); //Global Timeout
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(new Date() + " results:");
        for (int j : results) {
            System.out.println(new Date() + " " + j);
        }
    }
}

你会得到以下输出:

Wed Apr 29 10:51:02 CEST 2015 10 started
Wed Apr 29 10:51:02 CEST 2015 9 started
Timeout get for com.stackoverflow.q24473796.Job@249fe45c
Timeout get for com.stackoverflow.q24473796.Job@249fe45c
Wed Apr 29 10:51:07 CEST 2015 8 started
Wed Apr 29 10:51:07 CEST 2015 7 started
Wed Apr 29 10:51:11 CEST 2015 9 finished
Timeout get for com.stackoverflow.q24473796.Job@3cd4c5a0
Timeout get for com.stackoverflow.q24473796.Job@3cd4c5a0
Wed Apr 29 10:51:12 CEST 2015 6 started
Wed Apr 29 10:51:12 CEST 2015 5 started
Wed Apr 29 10:51:12 CEST 2015 10 finished
Wed Apr 29 10:51:14 CEST 2015 7 finished
Wed Apr 29 10:51:15 CEST 2015 8 finished
Wed Apr 29 10:51:17 CEST 2015 5 finished
Wed Apr 29 10:51:17 CEST 2015 4 started
Timeout get for com.stackoverflow.q24473796.Job@2a0fded2
Wed Apr 29 10:51:17 CEST 2015 3 started
Wed Apr 29 10:51:18 CEST 2015 6 finished
Wed Apr 29 10:51:20 CEST 2015 3 finished
Wed Apr 29 10:51:20 CEST 2015 2 started
Wed Apr 29 10:51:21 CEST 2015 4 finished
Wed Apr 29 10:51:21 CEST 2015 1 started
Wed Apr 29 10:51:22 CEST 2015 1 finished
Wed Apr 29 10:51:22 CEST 2015 2 finished
Wed Apr 29 10:51:22 CEST 2015 results:
Wed Apr 29 10:51:22 CEST 2015 5
Wed Apr 29 10:51:22 CEST 2015 4
Wed Apr 29 10:51:22 CEST 2015 3
Wed Apr 29 10:51:22 CEST 2015 2
Wed Apr 29 10:51:22 CEST 2015 1

【讨论】:

    【解决方案2】:

    您已经让 Jobs 在两个线程上运行,并且您正在从主线程读取结果。当您等待一个作业完成时,另一个作业正在运行,而您无需等待。如果将线程池的大小更改为 1,我认为您会发现您会得到预期的结果。

    如果您必须在多个线程上运行作业,则必须想出一种方法来跟踪在您开始等待结果时作业已经运行了多长时间。如果 Job 已经运行超过 5 秒,则拒绝它。如果没有,请等待 5 秒减去它已经运行的时间。

    一种选择是将开始时间存储在作业中。然后你可以做类似的事情

     long elapsedTime = System.currentTimeMillis() - job.getStartTime();
     if (elapsedTime < 5000) {
         future.get(5000 - elapsedTime, TimeUnit.MILLISECONDS);
     }
    

    【讨论】:

    • 我觉得这个主意不错。如何在 Callable 中保存开始时间,以便在调用主线程中使用它进行比较?但它不适用于 ExecutorCompletionService,因为返回的 Future 对象与提交到池中的顺序不同。所以我不知道什么 Future 对象属于什么 Callable 用于比较时间。
    • 是的,我也没有办法让 Job 与 Future 相关联。我发布了另一个可能被证明更有用的答案。
    【解决方案3】:

    您可以为此使用 ScheduledExecutorService。首先,您将提交每个任务并保留创建的期货。之后,您可以提交一个新任务,该任务将在一段时间后取消保留的未来。

     ScheduledExecutorService executor = Executors.newScheduledThreadPool(2); 
     for (int i = 10; i > 0; i--) {
            Job job = new Job(i * 1000, i);
            final Future handler = executor.submit(job);
            executor.schedule(new Runnable(){
                public void run(){
                    handler.cancel();
                }
            }, 5000, TimeUnit.MILLISECONDS);
            futures.add(handler);
     }
    

    这将执行您的处理程序(主要功能被中断)5 秒钟,然后将取消(即中断)该特定任务。

    此时你知道任何 Job 都不会被允许运行超过 5 秒,所以

    Integer content = future.get(5, TimeUnit.SECONDS);
    

    应该可以正常工作。

    【讨论】:

    • 该死,由于我的声誉很低,我无法在 8 小时内回复我自己的帖子。所以我会将我的更改添加到我的原始帖子中。
    【解决方案4】:

    可能最好的方法是在 Callable 的 call() 方法中处理时间。输入方法时,记录时间。在 call() 方法中分割时间 - 在示例情况下,不是完全睡眠,而是一次睡眠一秒钟 - 每次通过时,检查自进入时间以来是否已经过了最长时间。如果有,则中止处理并正常退出。

    如果您绝对不能定期检查 Callable 的代码 - 或者正如其他人所建议的那样,在外部停止通知上 - 有一种方法可以从线程外执行的代码中终止它。但是,这种方式已被弃用,因为它几乎肯定会导致无法修复的错误。本质上,当线程启动时——即当进入 call() 方法时——启动一个 TimerTask 子类并给它一个指向线程的指针。当 TimerTask 触发时,它会在线程上调用 Thread.stop()。同样,这是非常不安全的,因为它可能会使对象处于损坏状态,如此处的 Oracle 文档中所述:

    http://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html

    唯一可行的方法是,如果您的 Callable 的代码永远不需要同步,也永远不会在任何对象上实际同步,即使在库调用中也是如此,并且将来永远不会为此进行更改。这很难确保,因此最好找出一种方法来分解 Callable 的代码,以便它可以定期检查时间并在超时时优雅地退出。

    最后一点:如果你真的认为你的 Callable 的代码永远不需要同步来共享内存中的对象,那么它是在外部进程中执行的一个很好的候选者,而不是在主进程的线程中。这样做的好处是您可以相对安全地终止外部进程。基本上,外部进程中的 TimerTask 会在工作进程中调用 System.exit(),而不是在工作线程中调用 Thread.stop()。

    【讨论】:

    • 是的,我还考虑过在可调用对象中查找时间。问题是,在实际应用程序中,有一个大代码块而不是简单的 Thread.sleep(x);我不知道如何在不为每个线程创建新线程的情况下每秒检查此代码块!
    • 您是否希望线程在 5 秒后停止以节省处理时间,或者如果它们继续运行,您可以选择忽略结果,如果它们已经运行超过 5 秒而没有完成了吗?
    • 线程应该停止。在实际应用程序中,Callable 有时会陷入无限循环。所以我还需要在超时后杀死这些线程。真正的超时时间大约是半小时,所以它不是实时问题。这个被杀死的可调用的结果对我来说不再有趣了。但这也很有趣,Callable 被杀死了。
    • 有一种方法可以做到,但是非常危险。还有一种使用进程而不是线程的替代方法。有关详细信息,请参阅对我的答案的修改。
    猜你喜欢
    • 1970-01-01
    • 2011-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多