卜若的代码笔记-c#设计模式-享元模式

1.应用背景:大量new对象,且对象拥有相似元素,比如c/s架构里面client和server的一个关系,我们假如每次都会new一个新的对象用于处理client的请求,那么在server端就会产生大量的对象,从而导致内存溢出。

 

解决办法:享元模式,(一种池技术【对象池】)

 

实现过程:

1.我们有一个Server用来处理Client 的请求:它其实是一个工厂,并携带对象池

 

 public class Server
    {

        /// <summary>
        /// 对象池,说白了,就是一个存储对象的字典或者List=。=
        /// </summary>
        public static Dictionary<int, Client> poolDic = new Dictionary<int, Client>();

        public Server()
        {

            Thread thread = new Thread(run);
            thread.Start();

        }

        public void run()
        {
            Server.getInstance(1).requestInfo = "ssss";
            Server.getInstance(1).writeInfo = "ssss";
            
        }

        public static Client getInstance(int key)
        {
            if (poolDic.ContainsKey(key) == true)
            {

                return poolDic[key];

            }
            else
            {
                Client client = new Client(key);
                poolDic.Add(key, client);
                return client;
            
            }
        
        }

       
    


    }

 

2.定义请求对象Client

 public class Client
    {
        public Client(int _id)
        {

            this.ID = _id;
        }
        public int ID;
        public string requestInfo;

        public string writeInfo;

        public override string ToString()
        {
            string reStr = "";

            reStr += "ID:" + ID+"\n";
            reStr += "requestInfo:" + requestInfo + "\n";
            reStr += "writeInfo:" + writeInfo + "\n";
            return reStr;
        }
    }

3.简单的场景:

static void Main(string[] args)
        {

            Client client = Server.getInstance(1);
            client.requestInfo = "登录请求";
            client.writeInfo = "acc:123,psd:123";

            Client client2 = Server.getInstance(2);
            client2.requestInfo = "登录请求";

            client2.writeInfo = "acc:sdd,psd:sdd";


            Console.WriteLine(client.ToString());
            Console.WriteLine(client2.ToString());
          
            //这时,client2登录进去了,它进行了一个新的请求:更换签名

            Client client2_ = Server.getInstance(2);
            client2_.requestInfo = "进行了一个新的请求!";
            Console.WriteLine(client2_.ToString());

        }

4.运行结果和结果 说明:

我们看第三个ToString的信息,我们不难发现,其实这个对象是来自于对象池,而不是字典,从这个角度理解,我们可以确定,我们的享元模式是成功了的

 

5.线程安全

//在这个模式里面有个有趣的问题,如果我们分配给一个班级40个学生一人一个ID
            //然后我们使用多线程去处理这40个ID对应的Client的请求,这样做,它其实没问题
            //但假如,我们分成4个组,也就是对象池中只保存4个对象用来处理40个Client的通信,那就会遇到线程安全这种问题
            //什么是线程安全呢?
            //举个例子,就是说我线程A在处理AO对象时,是有一个时间的,在这个时间内我A还没处理完对象,B就开始对AO动手了
            //那么AO对象的数值就会被修改,修改成我们无法预测的状态,这是一个非常可怕的事情,尤其是C/S架构里面
            //举个例子,你在玩游戏,你在在商城里面购买了一些游戏币同时杀怪的时候,假如,有个傻逼程序员使用两个线程去处理
            //这一同时的动作Action,并且,操作的都是Client这个对象,在这个对象里面,存在一个公共值,叫做Value
            //购买命令发出时,Thread_purch对Value进行操作,然后Value  = 1000,同时,你杀怪的攻击1000000倍Thread_atk执行了
            //这时候Value = 1000000,然后Thread_purch返回给你1000000元宝(1:10)也就是说,你凭空赚了9900块,这家游戏公司倒闭是妥妥的


            //不知道你是否看懂了线程安全,现在,我们就面对一下在锐减对象时,产生的线程安全

 

 

我们定义一个方法,在对象里面写入数据

 我们定义两个Run方法并用Thread来运行它

我们来说明一下,为什么要这样做,我们的目的是检测多线程是不是会造成不安全,所以,我们给两个对象确定的相同的两个数据,也就是说Client里面的requestInfo和writeInfo应该是相同的,我们在场景中打印相关信息的时候,不应该出现不一样的情况,假如出现不一样的情况,那么久只有一种可能,那就是它的数据被其它线程给修改了,是吧?

 

我们来看一下检测的代码:

 

 

然后我们看一下结果:

 

显然,出现了线程不安全的情况。

 

6.怎么解决不安全的情况呢?

显然,答案是我们不要试图去共用一个对象,四十个客户就给它四十个客户好了,不要只给它四个Client 去处理四十个,这样很容易造成线程不安全的情况。

危险的时候还会造成线程的死锁,然后电脑宕机。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值