杂谈——由任务队列来讲代码与生活

我之前说过,我会关闭一切技术分享。这也意味着,我不会以任何形式去探讨技术。

在这里我分享的不是技术,而是思想。如果你从我说的东西里理解出了什么,完全是你自己的理解。

前面先发一段牢骚,不想看的话,直接跳转到后面红字开始的部分。


现在的时间是凌晨4点,看了三个小时的车珠子、男默女泪、我该怎么办的百度软文。我只能说唉,这个社会太浮躁了。或许作为我来讲,努力挣钱,随便找个相亲平台结个婚养育下一代才是正点。但对于我而言,我内心是真的不服输的。有时候特别想问很多事情……凭什么?


1月20日,去了一家公司“面试”,技术总监是曾经做谷歌音乐的。公司的位置让我并不想去,不是太远,相反,其实我骑车不到20分钟的路。不想去的原因是因为地理位置太过尴尬,涉及到家庭原因就不想多说什么了。

公司做医疗方面,心内科疾病数据。12年成立公司,15年7月启动项目。公司占地一间半写字楼,简易大长办公桌“高效办公”,最后一排是运营,然后……没什么可说的。让我想起了曾几何时的公司。

人文方面没什么可谈的,从运营只言片语听出来,公司做的发展方向是“免费推广”,和客户签协议……换句话说,也就是变向把数据拉到自己的平台上。心里一句呵呵……周鸿祎么?但你的公司是个A轮融资的公司哦。你早十年这么干是先进,但到现在看看,你的系统解决不了实际的客户方问题,你运营在你自己的模式下,他的意义呢……

恐怕就是烧投资的钱想做用户量、数据量。然后所谓先有“用户基础”再想其他。怎么变现,我以后再请个运营大牛就好了。


再看看黑板,黑板上写了不少东西……8条都是关于key的,按照语境翻译一下,应该就是关键词的意思了。这个key有权限控制,客户方和PM和负责的工程师都能加。而且key还有等级限制。……好吧,瞬间想到的思路满足这八条的方案就是把用户权限系统挂到Key上。然后Key取的时候异步Redis当缓存,变更的时候再通知,各种各种。再来看所谓的多接口,OK,这东西在医疗行业是个独揽的坑,虽然面试时候和人家说5万一个接口,但我的兄弟们做数据对接接口貌似20万也是有的。

黑板上写了Leader和三个项目组,好吧,PM职位在这家公司可以不考虑了,苦逼一个然后上面还有个管理,在上面是技术总监、人事、产品、实施,都是大爷。结合一下百度资料,公司注册资本111万元,然后全是软资质,没有硬性资质……

接下来谈,其实也就没什么好谈的了。这样的公司情况,这样的没有盈利的项目。我只能把话说的比较过分了。尖锐的问题“贵公司如果有一个行业巨头冲入市场,对市场进行抢占,那么贵公司将会怎么做?”

问题的目的不在他如何做,而是看公司的态度了。对方回答竞争,我肯定会接着往下问,竞争的资本。如果他的资本足够让我信服,我当然可以考虑。如果没有这个资本,哪些是潜在资本呢?从总监的位置上,就是“做好自己等着发工资”,这样的项目没上线就这样,还能指望上线么?

但对方的态度是“这种情况不会出现,如果出现了,那是投资人需要考虑的。投资人会比你更着急。”

我只能说,这样的总监,你会认为底下的人是个什么工作状态呢?

一个良好的团队,需要提供给有能力的人发展平台,也需要提供给混的人,混的平台。但,你带头者都是这样的状况,遇到风险先想到的是保本,先想到的是自己的股权能变现。也许他能成功,但我也只能抱着兼容并包的想法去看这件事了。


说的东西有点过分了,临走的时候,他问我说有没有自己觉得出彩的code segament。让我提供一下,就当作笔试了。我思考了一下,回家整理了一点东西,

发给他的代码是如下一段:

        /// <summary>
        /// 主VM构造逻辑(DEMO)
        /// by 阮清寒
        /// 2017年1月20日 
        /// </summary>
        public MainViewModel()
        {
            /// 粗略讲解一下这段代码
            /// 这段代码是手动实现了一个队列,不断从数据层读取数据,然后根据数据插入队列
            /// 当队列达到上限时,就等待下一个循环
            /// 同时维护一个“任务池”,这个任务池只能存放有限数量线程执行工作。
            /// 这里,将队列最后处理比作游乐园玩耍。将任务比作游客。游客排队进入游乐园。

            /// 通知端代理(如果解耦的话,这里应该把逻辑抽出去。)
            /// 连接代理商
            clientSocket.Connect(new IPEndPoint(ip, 1201));
            /// 游乐园时钟
            CommonTimer = new Timer(e =>
            {
                /// 当游乐园满了,就不再往游乐园放游客了。
                /// 利用return做代码优化,防止IL压入没用的代码。优化方式来自于Resharper
                if (TaskList.Count >= MaxCount) return;
                /// 循环放游客,直到队列慢
                for (int i = 0; i < MaxCount - TaskList.Count; i++)
                {
                    /// 如果游乐园里没有位置了,就别往里进了。
                    if (TaskQueue.Count <= 0) break;
                    /// 把游客从队列接出来
                    var k = TaskQueue.Dequeue();
                    /// 告诉游客玩完了,让游乐园把自己放出去。由于游乐园在自己的线程里,只能靠游乐园把游客清出去,然后游客就靠垃圾回收期去回收了。
                    k.ContinueWith(cw => App.Current.Dispatcher.Invoke(() => TaskList.Remove(k)));
                    /// 放游客进入游乐园
                    App.Current.Dispatcher.Invoke(() => TaskList.Add(k));
                    /// 游客开始玩吧!
                    k.Start();
                }
                   /// 每秒钟执行一次
            }, null, 0, 1000);
            /// 排队时钟
            CommonDBTimer = new Timer(e =>
            {
                /// 取出检票机
                var alllist = new GroupConfig()
                .GetModelList()
                .Where(
                    eal => eal.Config_Type == Password.GetMD5Hash(
                        Visit.ModelToJson(
                            new PasswordBoxModel()
                            {
                                Istrue = true,
                                GroupID = eal.Config_GroupID,
                                type = "IsAllwebSession",
                                dt = eal.Config_Time ?? DateTime.Now,
                            }
                        )
                    )
                ).ToList();
                /// 获取全部的游客
                var searchList = bll.GetSearchList();
                /// 如果队列里面游客的数量,是现在全部游客的2倍了。
                /// 说明至少每个人都玩了一次(抽屉原理)。
                /// 因此,这次就不让他们排了,等队伍小点再让他们进来玩。
                if (TaskQueue.Count > searchList.Tables?[0]?.Rows.Count * 2 || searchList.Tables?[0]?.Rows.Count <= 0) return;
                /// 告知每个游客,怎么玩。
                foreach (DataRow item in searchList.Tables?[0]?.Rows)
                {
                    ///先让他排上队。
                    TaskQueue.Enqueue(
                        /// 玩法是:
                        new Task(
                            /// 【创建新的搜索实例】(请无视类库命名……)
                            /// 创建游乐设施
                            () => new SearchHelper()
                            /// 游客可能有很多张票
                            /// 贵宾票就玩高级的模式
                            /// 没贵宾票就玩外围的模式
                            .SearchBaiDu(
                                alllist.IsdtHaveValue(item["SEK_AddGrop"].ToString()) ?
                                string.Format("{0} site:{1}", item["SEK_KeyWord"], item["LimitList_Url"]) :
                                string.Format("{0}", item["SEK_KeyWord"]
                            ))
                        /// 只让有票面而且不过期的项目列进来。
                        .Where(item2 => !string.IsNullOrEmpty(item2.Date))
                        /// 游玩项目列成列表
                        .ToList()
                        /// 让游客按照列表以此游玩
                        .ForEach(item2 =>
                        {
                            /// 如果成功游玩了记录给我们,并且通知给代理。
                            if (bill.Add(new Model(item2)) SendModelToClient(item2, item);
                        })));
                }
            /// 5秒照看一次
            }, null, 0, 5000);
        }

请先看过所有的代码,再阅读下面的文段,如果看不懂,请至少看过所有的注释。


在CSDN上,第一次发表自己的代码,这套游乐园,就是我所谓的任务队列。虽然写成这样子,但实际上这是为了过我自己心中代码段不超过50行的规矩,压缩起来实际上也只是四行代码罢了。注释写的很明白了,当然,有没有更好的做法呢?其实也是有的。因为一个游乐园用时间来控制是不恰当的。当时这个业务访问有超时问题,所以才会用这种写法。利用单位时间内无法完成就自动清人的方式把任务强行回收。


附上访问HTTP代码:


namespace ThomasVMControl.NetConnet
{
    using Newtonsoft.Json;
    using System.Net;
    using System.Text;
    using System.Threading.Tasks;
    public class Visit
    {
        public static async Task<string> HttpPost<T>(string Url, T data)
        {
            var p = new Task<string>(() =>
            {
                var webReq = (HttpWebRequest)WebRequest.Create(Url);
                webReq.ContentType = "application/json";
                var dt = string.IsNullOrEmpty(data?.ToString()) ? "" : ((data is string) ? data as string : ModelToJson(data));
                webReq.Method = string.IsNullOrEmpty(data?.ToString()) ? "GET" : "POST";
                var byteArray = Encoding.UTF8.GetBytes(dt);
                webReq.ContentLength = byteArray.Length;
                if (!string.IsNullOrEmpty(data?.ToString()))
                    using (System.IO.Stream newStream = webReq.GetRequestStream())
                        newStream.Write(byteArray, 0, (int)webReq.ContentLength);
                using (var response = (HttpWebResponse)webReq.GetResponse())
                using (var sr = new System.IO.StreamReader(response.GetResponseStream(), Encoding.UTF8))
                    return sr.ReadToEnd();
            });
            return await p;
        }
        public static async Task<string> HttpPost(string Url) => await HttpPost(Url, "");
        public static T JsonToModel<T>(string json) where T : new() => json != null ? JsonConvert.DeserializeObject<T>(json) : new T();
        public static string ModelToJson<T>(T mod) => JsonConvert.SerializeObject(mod);
        public static async Task<TB> HttpPost<TA, TB>(string url, TA mod) where TB : new() => JsonToModel<TB>(mod != null ? await HttpPost(url, mod) : await HttpPost(url));
    }
}

    /// WPF ViewModel基类
    public class ViewModelBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public void RaisePropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        protected void RaisePropertyChanged<T>(Expression<Func<T>> action) => RaisePropertyChanged(GetPropertyName(action));
        private static string GetPropertyName<T>(Expression<Func<T>> action) => ((MemberExpression)action.Body).Member.Name;
    }
像这样的代码,我没有去写注释,因为只是我自己来调用。大致看一下就好……囧rz


写的比较小巧的HTTP访问,实际使用的时候,在外层写了try-catch,然后设置了HTTP访问超时的设定,数据库那边连接也是。

然而……放这段代码出来意义呢?其实只是想说,代码你也许看不懂,但注释我相信认真看的话,会不会写程序的人,基本都看得懂吧。程序就是人的生活经验。有时候真的在想,我们是不是把程序脱离生活太远了。程序这东西,难的不是表象。真正难的是人对生活的理解。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值