ExecutorService that interrupts tasks after a timeout

后端 未结 9 2316
隐瞒了意图╮
隐瞒了意图╮ 2020-11-22 16:19

I\'m looking for an ExecutorService implementation that can be provided with a timeout. Tasks that are submitted to the ExecutorService are interrupted if they take longer t

9条回答
  •  粉色の甜心
    2020-11-22 16:43

    What about this alternative idea :

    • two have two executors :
      • one for :
        • submitting the task, without caring about the timeout of the task
        • adding the Future resulted and the time when it should end to an internal structure
      • one for executing an internal job which is checking the internal structure if some tasks are timeout and if they have to be cancelled.

    Small sample is here :

    public class AlternativeExecutorService 
    {
    
    private final CopyOnWriteArrayList futureQueue       = new CopyOnWriteArrayList();
    private final ScheduledThreadPoolExecutor                scheduledExecutor = new ScheduledThreadPoolExecutor(1); // used for internal cleaning job
    private final ListeningExecutorService                   threadExecutor    = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(5)); // used for
    private ScheduledFuture scheduledFuture;
    private static final long INTERNAL_JOB_CLEANUP_FREQUENCY = 1000L;
    
    public AlternativeExecutorService()
    {
        scheduledFuture = scheduledExecutor.scheduleAtFixedRate(new TimeoutManagerJob(), 0, INTERNAL_JOB_CLEANUP_FREQUENCY, TimeUnit.MILLISECONDS);
    }
    
    public void pushTask(OwnTask task)
    {
        ListenableFuture future = threadExecutor.submit(task);  // -> create your Callable
        futureQueue.add(new ListenableFutureTask(future, task, getCurrentMillisecondsTime())); // -> store the time when the task should end
    }
    
    public void shutdownInternalScheduledExecutor()
    {
        scheduledFuture.cancel(true);
        scheduledExecutor.shutdownNow();
    }
    
    long getCurrentMillisecondsTime()
    {
        return Calendar.getInstance().get(Calendar.MILLISECOND);
    }
    
    class ListenableFutureTask
    {
        private final ListenableFuture future;
        private final OwnTask                task;
        private final long                   milliSecEndTime;
    
        private ListenableFutureTask(ListenableFuture future, OwnTask task, long milliSecStartTime)
        {
            this.future = future;
            this.task = task;
            this.milliSecEndTime = milliSecStartTime + task.getTimeUnit().convert(task.getTimeoutDuration(), TimeUnit.MILLISECONDS);
        }
    
        ListenableFuture getFuture()
        {
            return future;
        }
    
        OwnTask getTask()
        {
            return task;
        }
    
        long getMilliSecEndTime()
        {
            return milliSecEndTime;
        }
    }
    
    class TimeoutManagerJob implements Runnable
    {
        CopyOnWriteArrayList getCopyOnWriteArrayList()
        {
            return futureQueue;
        }
    
        @Override
        public void run()
        {
            long currentMileSecValue = getCurrentMillisecondsTime();
            for (ListenableFutureTask futureTask : futureQueue)
            {
                consumeFuture(futureTask, currentMileSecValue);
            }
        }
    
        private void consumeFuture(ListenableFutureTask futureTask, long currentMileSecValue)
        {
            ListenableFuture future = futureTask.getFuture();
            boolean isTimeout = futureTask.getMilliSecEndTime() >= currentMileSecValue;
            if (isTimeout)
            {
                if (!future.isDone())
                {
                    future.cancel(true);
                }
                futureQueue.remove(futureTask);
            }
        }
    }
    
    class OwnTask implements Callable
    {
        private long     timeoutDuration;
        private TimeUnit timeUnit;
    
        OwnTask(long timeoutDuration, TimeUnit timeUnit)
        {
            this.timeoutDuration = timeoutDuration;
            this.timeUnit = timeUnit;
        }
    
        @Override
        public Void call() throws Exception
        {
            // do logic
            return null;
        }
    
        public long getTimeoutDuration()
        {
            return timeoutDuration;
        }
    
        public TimeUnit getTimeUnit()
        {
            return timeUnit;
        }
    }
    }
    

提交回复
热议问题