并发处理 - 记录 自己的处理过程

随着用户的增加,并发现象出现的频率越来越多 ,这时候如果没有做好并发处理 ,会造成数据的不一致,然后就需要增加一下锁,需要不同的用户 在 同一时间 仅能对一个 对象进行操作,为了 更好的拓展性,自己写了个类,用于来管理 并发请求,具体得逻辑 就是 每一个请求过来 获取唯一键值的对象,保证对于同一键值处理的请求获取到的是同一个对象,然后在对同一个对象其进行相关操作时,仅能一条一条处理,用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哈哈~

发布了36 篇原创文章 · 获赞 13 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_41392105/article/details/102915800
今日推荐