java executorservice持久队列

时间:2018-06-25 11:28:16

标签: java spring persistence executorservice

我实现了Spring-TaskExecutor(相当于JDK 1.5的Executor。)来处理从外部系统接收的通知通知。

只有一种方法的接口:

 public interface AsynchronousService {
    void executeAsynchronously(Runnable task);
}

和相应的实现:

public class AsynchronousServiceImpl implements AsynchronousService {

    private Executor taskExecutor;

    @Override
    public void executeAsynchronously(Runnable task) {
        taskExecutor.execute(task);
    }

    @Required
    public void setTaskExecutor(Executor taskExecutor) {
        this.taskExecutor = taskExecutor;
    }
}

任务执行器(旧版应用程序)的Xml配置:

<bean id="taskExecutor" class="org.example.impl.NotificationPool">
        <property name="corePoolSize" value="1"/>
        <property name="maxPoolSize" value="1"/>
        <property name="queueCapacity" value="100"/>
        <property name="WaitForTasksToCompleteOnShutdown" value="true"/>
</bean>

为corePoolSize和maxPoolSize都设置了1,因为我希望任务按顺序执行(处理任务的池仅创建1个线程)。

我想根据收到通知的日期对任务进行排序,因此我需要重写此功能以允许优先级排序:

public class NotificationPool extends ThreadPoolExecutorFactoryBean{
     @Override
     protected BlockingQueue<Runnable> createQueue(int queueCapacity) {
          return new PriorityBlockingQueue<>(queueCapacity);
        }
    }

ThreadPoolExecutorFactoryBean公开了“ createExecutor”方法,我确实重写了该方法以创建我们自己的Executor:

@Override
protected ThreadPoolExecutor createExecutor(int corePoolSize, int maxPoolSize, int keepAliveSeconds,
                                            BlockingQueue<Runnable> queue, ThreadFactory threadFactory,
                                            RejectedExecutionHandler rejectedExecutionHandler) {
    return new YourCustomThreadPoolExecutor (corePoolSize, maxPoolSize, keepAliveSeconds, TimeUnit.SECONDS, queue,
            threadFactory, rejectedExecutionHandler);

现在,在我的自定义线程池执行程序中,我可以覆盖默认的afterExecute回调:

public class YourCustomThreadPoolExecutor extends ThreadPoolExecutor {

    public YourCustomThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
    }

    @Override
    protected void afterExecute(Runnable r, Throwable t) {
        super.afterExecute(r, t);
        // Here do something with your exception
    }
}

这是Notification任务类:

public class NotificationTask implements Runnable, Comparable<NotificationTask> {

    private final NotificationService notificationService;
    private final Notification notification;

    public NotificationService(NotificationService notificationService, 
                               Notification notification) {
        this.notificationService = notificationService;
        this.notification = notification;
    }

    @Override
    public int compareTo(NotificationTask task) {
        return notification.getTimestamp().compareTo(task.getTimestamp());
    }

    @Override
    public void run() {
        notificationService.processNotification(notification);
    }
}

这就是我的执行方式:

asynchronousService.executeAsynchronously(new NotificationTask (notificationService, notification));

我不仅希望将队列存储在内存中,而且还希望将任务持久存储在数据库中,所以即使应用程序崩溃,我也可以拥有它们。

我想到的第一个解决方案是覆盖beforeExecute类中的默认YourCustomThreadPoolExecutor回调:

public class YourCustomThreadPoolExecutor extends ThreadPoolExecutor {

    public YourCustomThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
    }

@Override
protected void beforeExecute(Thread t, Runnable r) {
    // 1) serialize runnable object
    // 2) write in the database (with a flag if it is executed true/false)  
    super.beforeExecute(t, r);
}

    @Override
    protected void afterExecute(Runnable r, Throwable t) {
        super.afterExecute(r, t);

    }
}

现在的想法是,当我执行任务时,我将首先检查数据库,如果它存在未执行的任务(例如,通过检查布尔标志)。如果是,那么我首先获得此任务并执行它并更新标志。然后,我继续执行其他任务。因此,在这种情况下,如果应用程序在执行任务后崩溃,那么我仍然确保在应用程序再次运行后执行该任务,它不会丢失。您如何看待该解决方案?

首先,我试图找到一个挂接方法,然后将该任务放入队列,因此可以在其中执行任务的持久性。 (因为我宁愿在将任务放入队列之前先保留任务),但是我没有找到任何方法可以执行此操作,因此,我唯一的机会就是重写beforeExecutue方法。这当然不是很理想,因为我只是在将任务出队时才开始保留任务,因此如果应用程序崩溃,队列中的所有任务都会丢失。

0 个答案:

没有答案