工作中源代码学习

Spring_Quartz定时器---防止重复处理同一条记录(互

2019-01-18  本文已影响7人  ___TheOne___

1.背景

JavaWeb项目经常使用到定时器。如:Spring-Quartz等。
具体使用场景:“APP微信支付”异步获取支付结果:成功 or 失败,定时器异步处理将支付成功的订单,进行承保。

2.问题

定时器的执行频率,可以使用cron表达式指定,比如:每3秒执行一次。
如果执行频率过快,会导致同一条记录被重复处理,出现异常的响应结果。

3.解决方法

Method1:类静态变量---实现互斥锁
伪代码:

public class AJob {
      
      private static boolean isNotRun = true;

      public void methodA(){

          if(isNotRun){
              isNotRun = false;

              try{
                  //do something
              }
              finally{
                 isNotRun = true;
              }
          }//end if

      }//end method
}//end class

说明:
1.利用类静态变量isNotRun模拟互斥锁获取,只有isNotRun为true才执行任务方法,否则跳过;
2.获取到之后,在方法执行过程中,将isNotRun设置为false;
3.try-finally使用,保证isNotRun一定可以被释放。

Method2:利用AQS实现类Mutex---实现互斥锁

public class AJob {
      
      private final Lock lock = new MutexLock();    //自定义互斥锁实现

      public void methodA(){

        if (lock.tryLock()) {  
           try {  
              // do something  
           } finally {  
              lock.unlock();  
           }  
        } //end if

     }//end method
}//end class

说明:此用法可确保如果获取了锁, 则会释放锁; 如果未获取锁, 则不会试图将其释放.

附件:MutexLock源码(基于AQS实现互斥锁):

import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

class MutexLock implements Lock, java.io.Serializable {

    // Our internal helper class
    private static class Sync extends AbstractQueuedSynchronizer {
        // Reports whether in locked state
        protected boolean isHeldExclusively() {
            return getState() == 1;
        }

        // Acquires the lock if state is zero
        public boolean tryAcquire(int acquires) {
            assert acquires == 1; // Otherwise unused
            if (compareAndSetState(0, 1)) {
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }

        // Releases the lock by setting state to zero
        protected boolean tryRelease(int releases) {
            assert releases == 1; // Otherwise unused
            if (getState() == 0) throw new IllegalMonitorStateException();
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }

        // Provides a Condition
        Condition newCondition() {
            return new ConditionObject();
        }

        // Deserializes properly
        private void readObject(ObjectInputStream s)
                throws IOException, ClassNotFoundException {
            s.defaultReadObject();
            setState(0); // reset to unlocked state
        }
    }

    // The sync object does all the hard work. We just forward to it.
    private final Sync sync = new Sync();

    public void lock() {
        sync.acquire(1);
    }

    public boolean tryLock() {
        return sync.tryAcquire(1);
    }

    public void unlock() {
        sync.release(1);
    }

    public Condition newCondition() {
        return sync.newCondition();
    }

    public boolean isLocked() {
        return sync.isHeldExclusively();
    }

    public boolean hasQueuedThreads() {
        return sync.hasQueuedThreads();
    }

    public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }

    public boolean tryLock(long timeout, TimeUnit unit)
            throws InterruptedException {
        return sync.tryAcquireNanos(1, unit.toNanos(timeout));
    }
}

4.文章引用:

1.java并发编程--互斥锁, 读写锁及条件

上一篇 下一篇

猜你喜欢

热点阅读