併發處理 - 記錄 自己的處理過程

隨着用戶的增加,並發現象出現的頻率越來越多 ,這時候如果沒有做好併發處理 ,會造成數據的不一致,然後就需要增加一下鎖,需要不同的用戶 在 同一時間 僅能對一個 對象進行操作,爲了 更好的拓展性,自己寫了個類,用於來管理 併發請求,具體得邏輯 就是 每一個請求過來 獲取唯一鍵值的對象,保證對於同一鍵值處理的請求獲取到的是同一個對象,然後在對同一個對象其進行相關操作時,僅能一條一條處理,用synchronized關鍵字來限制即可,大概畫了一下原理圖,每根線對應一個 請求,用完之後將其釋放
在這裏插入圖片描述
下面是這個管理類的實現代碼:

package com.mx.util;

import java.util.HashMap;

public class MxObjectLockUtil {
    private   HashMap<String,PlanLock> planLockHashMap = new HashMap<>(40);
    private static volatile MxObjectLockUtil instance;

    private MxObjectLockUtil(){

    }

    public HashMap<String, PlanLock> getPlanLockHashMap() {
        return planLockHashMap;
    }

    public synchronized PlanLock getObjectLock(String key){
        if (planLockHashMap.get(key) == null){
            PlanLock planLock = new PlanLock();
            planLockHashMap.put(key,planLock);
            System.err.println("生成:" + key);
            return planLock;
        }
        return planLockHashMap.get(key);
    }

    public  void removeLock(String key){
        if (planLockHashMap.get(key) != null){
            PlanLock planLock =  planLockHashMap.remove(key);
            System.err.println("移除:" + key + ";對象:" + planLock);
        }
    }

    public static MxObjectLockUtil getInstance(){
        if (instance == null){
            synchronized (MxObjectLockUtil.class){
                if (instance == null){
                    instance = new MxObjectLockUtil();
                }
            }
        }
        return instance;
    }

    class PlanLock{
        public synchronized void run(Runnable runnable){
            runnable.run();
        }
    }

}


然後寫了個測試類,看效果

package com.mx.util;

import java.util.Random;

public class Test {
	public static MxObjectLockUtil mxObjectLockUtil;

	public static void main(String[] args) {
		mxObjectLockUtil = MxObjectLockUtil.getInstance();
		Random random = new Random();
		for (int i = 0; i < 10; i++) {
			new Thread(new Runnable() {
				@Override
				public void run() {
					String key = random.nextInt(1) + "";
					mxObjectLockUtil.getObjectLock(key).execute(new sleepRunabble(key, 400));
					mxObjectLockUtil.removeLock(key);
				}
			}).start();
		}
	}

	static class sleepRunabble implements Runnable {
		private String id;
		private long times;

		sleepRunabble(String id, long times) {
			this.id = id;
			this.times = times;
		}

		@Override
		public void run() {
			System.out.println("我是" + id);
			try {
				Thread.sleep(times);
				System.out.println(id + "延遲" + times + "ms");
				System.err.println(mxObjectLockUtil.getPlanLockHashMap().size());
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

這是測試10個線程操作1個對象的時候
在這裏插入圖片描述
正常,並沒有出現同時 我是0的編號或同一個編號在延遲,
下面來測試 同時1000個線程,對200個對象操作的情況,測試代碼如下:

package com.mx.util;

import java.util.Random;

public class Test {
	public static MxObjectLockUtil mxObjectLockUtil;

	public static void main(String[] args) {
		mxObjectLockUtil = MxObjectLockUtil.getInstance();
		Random random = new Random();
		for (int i = 0; i < 10000; i++) {
			new Thread(new Runnable() {
				@Override
				public void run() {
					String key = random.nextInt(200) + "";
					mxObjectLockUtil.getObjectLock(key).execute(new sleepRunabble(key, 50));
					mxObjectLockUtil.removeLock(key);
				}
			}).start();
		}
	}

	static class sleepRunabble implements Runnable {
		private String id;
		private long times;

		sleepRunabble(String id, long times) {
			this.id = id;
			this.times = times;
		}

		@Override
		public void run() {
			System.out.println("我是" + id);
			try {
				Thread.sleep(times);
				System.out.println(id + "延遲" + times + "ms");
				System.err.println(mxObjectLockUtil.getPlanLockHashMap().size());
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

在這裏插入圖片描述
依舊沒有同時 同一個編號在延遲或生成的,完全說明了這個方法是可行的,效率也還可以,當10000個對200對象操作請求發來時,差不多平均每50個線程是對同一個對象,這50個對象 依次拿到 同一個對象,然後依次執行 ,主要耗時,僅是,剛開始獲取分配對象時,後續基本就是200個不對對象同時操作

如有更好的建議或有誤的地方,請評論出來,我也在不斷的學習和提升中,只爲更高的技術,更好的明天,O(∩_∩)O哈哈~

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