关于ArrayBlockingQueue队列的一些问题

背景:最近接手一个新的应用-商机快递,主要是给用户发送营销邮件,由于不定期会有漏发的情况,所以在里面加了一些逻辑来修复这个问题,由于系统采用了多线程的方式,改之前考虑的不周全,最后会导致重发的现象。

系统初始时会实例一个ThreadPoolExecutor对象(exec)。ThreadPoolExecutor是并发包中一个提供线程池的服务,可以很容易将一个实现了Runnable接口的任务放入线程池中执行。具体的execute(Runnable)方法执行过程为:

首先判断传入的Runnable对象是否为null,如果为null直接抛出NullPointException异常。如果不为空执行下面步骤

如果当前的线程数小于配置的corePoolSize,则调用addIfUnderCorePoolSize方法进而会调用mainLock锁。

如果当前的线程数小于配置的corePoolSize并且线程处于RUNNING状态,调用addThread增加线程,

addThread方法首先创建Worker对象,然后调用threadFactory( Thread newThread(Runnable r); )创建新的线程,如果创建新的线程不为null时,将Worker对象的thread属性指向此创建出来的线程,并将此Worker对象放入到workers中,最后增加当前线程池中的线程数。

用代码描述为:

--------------------------

原来的做方法是

一个线程执行doPerform方法,会改biz_express_daily表中的记录的ip,然后再执行takeCareOf方法来发邮件,发送成功后会将记录的status字段值改掉,但是关键的是在完成status改掉之前会有一段时间。

另外的线程调用doPerform方法,此时bizexpresses 为空,进入到if分支,调用doContinue方法。

此时的bizexpresses 是有值的,而且取出来的正好是刚才第一个线程里面的值,然后同样执行takeCareOf方法发送邮件。

这样就会造成邮件的重发,当然根据线程抢占的激烈程度,会导致重发邮件的数量也不一致。

你可能感兴趣的:(关于ArrayBlockingQueue队列的一些问题)