java 利用cas算法模擬多線程併發搶票

利用cas算法實現。基於樂觀鎖。如果值發生衝突。加入異步線程遞歸進行搶(設置遞歸次數。防止死循環)

1、創建ThreadUtils類

/**
 * 線程副本,保證數據
 */
public class ThreadUtils {
    private static ThreadLocal<Integer> threadLocal;
    static{
        threadLocal = new ThreadLocal();
    }

    public static void set(int value){
        threadLocal.set(value);
    }

    public static Integer get(){
        return threadLocal.get();
    }
}

2、創建CasUtils類

/**
 * 基於cas原理實現高併發
 */
public class CasUtils implements Runnable{
    /**
      * 私有內部類創建單例
     */
    private static class AtomicHolder{
        private static volatile AtomicInteger s = new AtomicInteger(ThreadUtils.get());
    }

    /**
     * 線程池
     */
    private  static ThreadPoolExecutor ex;
    static {
         ex = new ThreadPoolExecutor(
                10,10,5,TimeUnit.SECONDS,
                new ArrayBlockingQueue<Runnable>(1),
                new ThreadPoolExecutor.DiscardOldestPolicy());

    }

    public CasUtils()throws Exception{
        int value = ThreadUtils.get();
        if(!AtomicHolder.s.compareAndSet(value,value)){
            /**
             * 此處對於未賦值的進行其他操作
             */
        }
    }

    @Override
    public void run() {
        System.out.println("我在搶票中..."+Thread.currentThread());
        try {
            int value = AtomicHolder.s.get();
            int si = 0;
            if(value-1>=0&&(si=AtomicHolder.s.decrementAndGet())>0){
                /**
                 * 涉及業務可以寫入消息隊列
                 */
                System.out.println("搶票成功..."+Thread.currentThread()+"========"+(si));
            }else{
                /*if(value-1<0){
                    System.out.println("暫無票..."+Thread.currentThread()+"========"+(si));
                    return;
                }*/
                ex.execute(new Runnable() {
                    @Override
                    public void run() {
                        System.out.println("搶票循環..."+Thread.currentThread());
                        boolean isSubmit = true;
                        //設置搶票循環次數。
                        int time = 0;
                        while(isSubmit){
                            ++time;
                            int value = AtomicHolder.s.get();
                            //超過10次結束
                            if(time>=10){
                                System.out.println("搶票結束【未搶到】..."+Thread.currentThread());
                                isSubmit = false;
                                break;
                            }
                            if(value-1>=0&&AtomicHolder.s.decrementAndGet()>0){
                                /**
                                 * 涉及業務可以寫入消息隊列
                                 */
                                isSubmit = false;
                                System.out.println("搶票成功..."+Thread.currentThread());
                            }
                            try {
                                Thread.sleep(200);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                });
            }
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

 

3、執行
public static void main(String[] args) throws Exception {
    for(int i=0;i<100;i++){
        ThreadUtils.set(10);
        new Thread( new CasUtils()).start();
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章