我希望在Java中实现生成任务的机制。实际上,任务所做的与此处无关,可以通过线程或新进程来完成。

我真正需要的是:

  • 可以将任务设置为重试N次
  • 如果任务中发生令人讨厌的事情,则生成它的父对象将受到保护
  • 以上两个都应该从我身上抽象出来

  • 有谁知道用Java可以做到这一点的框架吗?

    最佳答案

    我已经考虑了很长时间了,终于得到了一些您认为有用的东西。

    我们的小“框架”的第一部分是Task接口(interface):

    public interface Task {
        void work();
        void stop();
    }
    

    实现这一点,我们可以设置我们的WorkTask:
    public class WorkTask implements Task {
        @Override
        public void work() {
            // Do something useful...
            // might throw SomethingNastyHappenedException
        }
    
        @Override
        public void stop() {
            // implement as needed e.g. to break inner loops
        }
    
    }
    

    为了符合您能够重试的要求,我们创建了Wrapper类:
    public class RetryingTaskWrapper implements Task {
        private Task wrappedTask;
        private int maxTries;
        private boolean running = false;
    
        public RetryingTaskWrapper(Task wrappedTask, int maxTries) {
            this.wrappedTask = wrappedTask;
            this.maxTries = maxTries;
        }
    
        @Override
        public void work() {
            running = true;
            boolean success = false;
            int tries = 0;
    
            while (running && !success && tries < maxTries) {
                try {
                    wrappedTask.work();
                    success = true;
                } catch (SomethingNastyHappenedException e) {
                    // something nasty happed so retry
                    tries++;
                } catch (Exception e) {
                    // something even worse happened -> end
                    running = false;
                }
            }
    
            running = false;
        }
    
        @Override
        public void stop() {
            running = false;
            wrappedTask.stop();
        }
    }
    

    最后,我们需要一些东西来执行任务...
    public class TaskRunner implements Runnable {
        private Thread thread;
        private Task task;
        private boolean running = false;
    
        public TaskRunner(Task task) {
            this.task = task;
        }
    
        public synchronized void start() {
            if (thread != null) {
                return;
            }
    
            thread = new Thread(this);
            thread.start();
        }
    
        @Override
        public void run() {
            running = true;
    
            if (task != null) {
                try {
                    task.work();
                } catch (Exception e) {
                    // log your exception
                }
            }
    
            thread = null;
            running = false;
        }
    
        public void stop() {
            if (running) {
                if (task != null) {
                    task.stop();
                }
                if (thread != null) {
                    thread.interrupt();
                }
            }
        }
    }
    

    现在,我们需要做的就是设置一个TaskRunner并启动它:
    WorkTask workTask = new WorkTask();
    TaskRunner runner = new TaskRunner(new RetryingTaskWrapper(workTask, 5));
    runner.start();
    

    如果您只想运行一次WorkTask而不重试,那也是可行的:
    WorkTask workTask = new WorkTask();
    TaskRunner runner = new TaskRunner(workTask);
    runner.start();
    

    如果您愿意,甚至可以无限循环运行WorkTask,而不必更改WorkTask本身。您所需要做的就是创建另一个包装器
    public class InfiniteLoopTaskWrapper implements Task {
        private Task wrappedTask;
        private boolean running = false;
    
        public InfiniteLoopTaskWrapper(Task wrappedTask) {
            this.wrappedTask = wrappedTask;
        }
    
        @Override
        public void work() {
            running = true;
    
            while (running) {
                try {
                    wrappedTask.work();
                } catch (SomethingNastyHappenedException e) {
                    // log that something nasty happened
                } catch (Exception e) {
                    // something even worse happened -> end
                    running = false;
                }
            }
        }
    
        @Override
        public void stop() {
            running = false;
            wrappedTask.stop();
        }
    
    }
    

    并运行它...
    WorkTask workTask = new WorkTask();
    TaskRunner runner = new TaskRunner(new InfiniteLoopTaskWrapper(workTask));
    runner.start();
    

    09-27 11:14