雪中徒步前的准备

这周六要去临安窑头山徒步, 春节末尾的时候团队的几个成员已经探过一次路。当时雪已经有到人脚踝那么厚了,最近今天临安依旧是大雪,等到我们徒步的时候,山上的雪应该会很厚了。 临安今日雪景 探路回来,同伴已经决定此次徒步要让大家都带上雪爪。我虽然已经徒步好几年了,但是之前去的山上都是没什么雪的,所以这玩意我也是没准备过。疫情原因,也是好久没爬了。之前的背包,登山杖什么的丢的丢,坏的坏,这次一起去置办了去。 总计需要以下几样东西,下班后一起迪卡侬置办了。 登山包。这次打算搞个小点的,之前的30升实在太大了,咱也没有要背帐篷的需求。 登山杖。要准备两根了,雪这么大,还是两个牢靠点。 手套。下雪天还要弄个好的,要不手太冷。用手套堆起雪人来也不冻手。 雪爪。这玩意一年用不了两次,不过这么大的雪还要准备一个的。 头灯。说来惭愧,徒步3年了,算是半个领队了,竟然没准备。这次八成下山天要黑,搞一个了。 手机背包夹。打算沿路用手机录个像,用它可以解放双手,要是感觉好,后面可以弄个专业的录像设备。这玩意也不知道迪卡侬有没有。

2022-02-09 16:17 · 1 min · 江波·林沂

Java基础性问题

Java的内存模型知道吗 (1)Java所有变量都存储在主内存中 (2)每个线程都有自己独立的工作内存,里面保存该线程的使用到的变量副本(该副本就是主内存中该变量的一份拷贝) 集合你平时用的多的有哪些 答: 集合的话像Collection下的ArrayList, LinkedList; Set下的HashSet; Map下的HashMap,如果涉及到多线程,线程安全的话,会使用ConcurrentHashMap。 问:我们先聊一下ArrayList和LinkedList吧,它们两个在什么场景下会使用它? 答:ArrayList的底层数据结构是数组,不指定ArrayList大小的时候初始化的大小是0,第一次add的时候size会变成10,扩容的话会是之前的1.5倍。扩容因子默认时0.75,也就是原始大小是10,写入第8个元素的时候,数组长度会扩容至15; ArrayList由于底层是数组,因此随机查找的速度很快,插入和删除效率比较低。也因为它的底层是数组,因此分配内存空间的时候要求是连续的内存单元,所以如果需要存储的数据量很大的情况下,不建议使用ArrayList,因为可能不大容易在jvm中找到这么一大块连续空间,会导致大的GC。 LinkedList的底层是一个带有头节点和尾节点的双向链表,提供了头插(LinkedFirst)和尾插(LinkedLast),插入和删除比较快,不支持随机查询,LinkedList数据的存储不要求内存空间是连续的。 常规的来聊一下HashMap 答:HashMap在1.7的时候底层使用数组+单链表的数据结构,使用的是头插;1.8使用数组+单链表/红黑树,使用的是尾插。单链表和红黑树之间的转换,当单链表的长度大于等于8,并且它的hash桶大于等于64的时候,它会将单链表转换成红黑树形式存储;它在红黑树的节点的数量小于等于6的时候,它会重新再转换成一个单链表,这是它底层结构的一个变化;当我们往hashmap中put元素的时候,先根据key的hash值得到这个元素在数组中的位置(即下标),然后就可以把这个元素放到对应的位置中了。如果这个元素所在的位子上已经存放有其他元素了,那么在同一个位子上的元素将以链表的形式存放,新加入的放在链头,最先加入的放在链尾。从hashmap中get元素时,首先计算key的hashcode,找到数组中对应位置的某一元素,然后通过key的equals方法在对应位置的链表中找到需要的元素。从这里我们可以想象得到,如果每个位置上的链表只有一个元素,那么hashmap的get效率将是最高的;另外一点是关于它Hash桶的数量,默认是16个,默认的阀值是0.75,这关系到它的扩容。 问:它扩容是怎么扩容的? 答:扩容的时候首先检测数组中的元素个数,负载因子默认是loadFactor=0.75,因此当它哈希桶占用的容量大于12的时候,就会触发扩容,哈希桶会扩容成之前的两倍,把之前的元素再进行一次哈希运算,然后添加到新的哈希桶,然后按照链表或者红黑树重新排列起来。 问:你给我说下它是不是线程安全的? 答:它不是线程安全的,因为在插入操作的时候多线程会有数据覆盖的可能;另外它在1.7的时候,它在put的时候可能会有一个resize的过程,这个过程可能会照成它的头插会形成一个环形链表形成一个死循环,1.8之后改成尾插了。 问:你平时开发的时候怎么去保证它的线程安全? 答:我平时开发的时候会使用ConcurrentHashMap来保证它的线程安全。 问:聊一聊ConcurrentHashMap 答:1.7的时候底层是一个分片数组,使用了segment锁(继承自ReentrantLock),通过每次只给一个段加锁来保证它的线程安全和并发度;另外,在1.8的时候,它改成了和HashMap一样的数据结构,使用数据加单链表或者红黑树的数据结构,在1.8的时候渐渐放弃了这种分片锁机制,而使用的是synchronized加CAS来做的,我们知道在1.6版本的时候JVM对synchronized的优化是非常大的,现在也是用这个方法来保证线程安全。 问:CAS是什么? 答:Compare And Sweep,比较并替换,是乐观锁的一种实现,在修改之前要将之前读到的值与当前内存中的值进行比较,如果一致就写入。CAS可以认为是一种轻量级的锁,在低并发的时候时候效率很快,在高并发的情况下,CAS需要涉及到CPU的计算,容易引起CPU性能的消耗,高并发的情况下还是建议使用状态机或者锁之类的。另外一点就是会产生ABA的问题,因为在读取和写入之间,可能有其他线程率先完成修改,然后又将值改回到之前,这样就误以为当前的值和读取的值是一致的,这个问题可以通过加一个戳或标志位来标识,也就是相当于加个版本号。 刚你提到了synchronized,再跟我聊下它 答:关于synchronized,可以用在同步代码块(可指定任意锁)/方法(指定this)/静态方法(指定class对象)。在1.6升级还是蛮大的,首先提供了无锁状态,然后是偏向锁,然后是轻量级锁,然后是重量级锁。偏向锁的话,见名知意,它偏向于获得第一个锁的线程,它会将id写到锁对象的对象头中,等其他线程来的时候,立即会升级到轻量级锁的状态(如果是同一个线程再次进入,先判断是否获取过锁,如果获取过标记位+1,否则修改为1),轻量级锁主要是在低并发的情况下来消除锁的方式,它主要是在你的虚拟机栈中开辟一个空间,叫做Lock Record,将锁对象的Mark Work写到Lock Record,再尝试Lock Record的指针使用CAS去修改锁对象头的那个区域来完成一个加锁的过程,如果再有线程进入的话,并尝试修改这个指针,轻量级锁会升级为一个自旋锁,如果10次未成功就会膨胀成一个重量级锁,也就是一个互斥锁的过程。重量级锁,使用synchronized的时候会在你的代码块前后加上两个指令,monitorenter和monitorexist,通过一个monitor监视器通过计数器的方式来监视这个锁的状态。如果是同步方法的时候,使用的是一个ACC_SYNCHRONIZED标志位,相当于flag,它自动走的是一个同步方法调用的策略,这个原理是比较简单的。 synchronized 的代码块同一时间,只能有一个线程可以进入执行,也就满足了代码块整体的原子性,可见性,有序性。 问:什么时候用它?什么时候用ReentrantLock,这个你有考虑吗? 答:有,它两对比的话区别还是蛮大的。从JVM层面来说,synchronized是JVM的一个关键字,ReetrantLock其实是一个类,你需要手动去编码,synchronized使用其实是比较简单的,不需要关心锁的释放;但是使用ReetrantLock的时候你需要手动去lock,然后配合try finally然后去确保锁的释放,然后ReentrantLock相比synchronized有几个高级特性,当一个线程长期等待得不到锁的时候,你可以手动的去调用一个lockInterruptibly方法尝试中断掉不去等待;另外,它提供了一个公平锁的方式;此外,它提供了一个condition,你可以指定去唤醒绑定到condition身上的线程,来实现一个选择性通知的方式。如果不需要ReentrantLock需要的高级特性的话,建议还是使用synchronized的关键字。 例:因为锁不可逆,如果在早高峰的时候,滴滴打车上的所有锁都升级为重量级锁,那么等过了这个高峰,锁依然是重量级锁,会影响系统的QPS的,所以在使用的时候还是要更具具体的场景来使用 volatile看过吗? 参考知道这些,面试时volatile就稳了 答:volatile修饰的变量保证了多线程下的可见性,当CPU写数据时,发现此变量被volatile修饰时,发现其他CPU中也存在该变量的副本,会发出信号通知其他CPU该变量的缓存行置为无效状态,因此当其他CPU需要读取这个变量时,发现自己缓存中的变量行是无效的,就重新去内存读取。它是通过计算机的总线嗅探机制(MESI)来实现的,当然它也会照成一个问题,就是volitale会一直嗅探,导致一些无效的交互,引发总线风暴。 volatile是JVM提供的轻量级的同步机制。保证可见性,保证有序性,禁止指令重排,不保证原子性(需要借助synchronized或者CAS) 问: volatile 如何保证的有序性 volatile 可以通过添加内存屏障来保证有序性。这里需要先介绍另外一个东西,叫 happens-before 原则.我举其中的一个例子你们感受一下,一个线程内,按照代码顺序,书写在前面的操作先行发生于书写在后面的操作,呃呃这种我们看起来不是很正常的嘛,原理就是 JVM 在后面默默付出呀,但是!我们的 JVM 为了优化我们的代码,它还会进行指令重排!一行代码可能不单单只有一个指令呀,就是这个指令重排让我们原本有序的代码变成了无序的指令,所以可能会出现安全问题。...

2022-02-09 14:57 · 1 min · 江波·林沂

Dubbo相关知识点

Duboo核心能力 面向接口代理的高性能RPC调用 提供高性能的基于代理的远程调用能力,服务以接口为粒度,为开发者屏蔽远程调用底层细节。 智能容错和负载均衡 内置多种负载均衡策略,智能感知下游节点健康状况,显著减少调用延迟,提高系统吞吐量。 服务自动注册和发现 支持多种注册中心服务,服务实例上下线实时感知。 高度可扩展能力 遵循微内核+插件的设计原则,所有核心能力如Protocol、Transport、Serialization被设计为扩展点,平等对待内置实现和第三方实现。 运行期流量调度 内置条件、脚本等路由策略,通过配置不同的路由规则,轻松实现灰度发布,同机房优先等功能。 可视化的服务治理与运维 提供丰富服务治理、运维工具:随时查询服务元数据、服务健康状态及调用统计,实时下发路由策略、调整配置参数。 Dubbo2与Dubbo3的区别 dubbo2的服务注册是基于接口的,dubbo3的服务注册时基于应用的,这会带来几点好处。首先,对于注册服务来说,其的负载将会降低很多,因为接口比应用至少是多了一个数量级的;其次,对于服务治理来讲,常见的情景是屏蔽某个应用的在某个实例上的所有接口,这种情景下,基于应用的注册显而易见更好处理。当然,由于dubbo3为了dubbo2可以更好的平滑迁移,默认还是基于接口注册的。

2022-02-09 10:57 · 1 min · 江波·林沂

个人网站Hugo增加shortcodes

前几天个人网站从wordpress迁移到了hugo。虽然是纯人工的,但是一切还算顺利。美中不足的文章原来图片上面的描述不见。之前图片描述是通过在markdown中自定义html实现的。没想到同样的方式到了hugo就不生效了。类似于下面这种代码直接加到md的。 <p style="text-align:center;font-size:0.5em;">图片描述</p> 当时着急迁移,也就没细究,今天正好有空研究了下。 Hugo并不支持在md文档中直接添加html代码,我使用的主题paperMod更是直接将markdown中的html直接忽略。还好hugo已经考虑到了这种情况,它使用Shortcodes来解决这种扩展性的问题。 hugo添加Shortcodes的方式如下: 找到你对应的hugo主题下的layouts>shortcodes目录。在目录下新建你自定义的html文件, 并在里面添加自定义的html代码。例如新加了文件imgda.html. <p style="text-align:{{ index .Params 0 }};font-size:0.5em;">{{ index .Params 1 | markdownify }}</p> 直接在md中使用的shortcodes即可。请忽略下方代码的\ \{\{\<imgda center 测试\>\}\} 最终在页面上展示的代码将变为如下形式。 <p style="text-align:center;font-size:0.5em;">测试</p> 这样一波下来,完美解决我的图片描述不显示的问题。有相同需求的同学都可以用我这种方式试试。

2022-02-08 15:22 · 1 min · 江波·林沂

2022年春节历程

这已经在第二个在上海过的春节了 今天中午在和同事吃饭的时候在吐槽,今年过节没回去,出去吃个饭外面的小摊大部分都关门了。同事回了句,今年当然关门的多,很多人今年都赶着回去了。 仔细一想,还真是。去年在上海过年的时候,外面的小店还是有很多开着的。毕竟去年政府号召的是就地过年,连的这很多小商小贩都没回去。而他们算是没有五一,十一的,所以很多人算起来已经两年没回家了。今年政府没有再说就地过年,所以很多人都早早的回去了。 今年的春节假期第一天对我来说都是艰难的,公司额外多给了一天假期,但就这我在假期的第一天买菜时,菜还是不出意料的涨价了不少。老板一边买一边还说,下午就关门了,要买就赶快买了。虽然贵了不少,终究还是买到了菜。 本来打算是过年在家自己蒸点馒头和炸点油条的。但越临近假期,越是懒。开始想的是油条就不搞了,后面就单独弄点馒头吧。后面连馒头都不想搞了,还是买吧。可惜的是,等我放假,门口的几家包子店早关门了,其中一个还是连锁的那种。唉! 又不可能不吃馒头了,于是下午便开始满大街的找馒头店。多走了两个路口,看到旁边有人拎着大袋的馒头,我的心也就放了下来。没走多久,终于看到了开着的馒头店。 这个馒头店的味道还是不错了,买完的路上我们就消灭了2个。馒头透着一股清香,跟老家的馒头也没差多少,属实好吃。其实离我家也没多远,主要还是之前懒,没几次跑过这么远的地。 除夕的伙食是以一顿羊肉火锅开始的。今年过年是啥也没准备,懒省事当然还是火锅最好了。羊肉是在我工作日中午最常吃的牛肉面旁边买点,我包圆了他家最后的三块羊肉。配菜就是昨天在菜市场买的,其他的还有就是去年5.1回去拿来的还没有吃完的粉条 。羊肉旁边买来的准备炒菜用的小狮子头也被我用来涮火锅了。 火锅这玩意一吃就上瘾,后续春节期间又吃了3,4次。基本都是以羊肉打底,蔬菜涮之。粉条,狮子头偶尔点缀。今年吃火锅的时候也没有喝点啤酒什么的,想想去年,咱可是用白啤掺着黑啤灌的。 今年春节喝的主要是橙汁。最后一天去山姆本来是陪同事的,但是自己后面终究也是买了一大堆的。其中最主要的就是橙汁,本来是去拿青柠汁的,这玩意算是山姆的招牌饮品吧,几乎是人手一件。橙汁就放在它的旁边,看着颜色还不错,就顺手拿了一瓶。眼神瞄过,有促销活动,买二减十,这不就相当于5折码?最终扛回来了两瓶。 味道怎么样呢?感觉跟我小时候喝的汇源橙汁差不多,味道不错,但是后味太苦,也不清楚什么情况,大多数人估计还是喝不惯的。看了看配方表,也就只有橙汁和橙果肉,也是奇怪。自己鲜榨的橙汁也不是这个味道啊。 上海的大年初一实在有些冷清,去年的今天因为小区实在太冷清,我们特意跑去了热闹的豫园。不过豫园似乎太热闹了,今年我们家的怀着个大肚子,明显是不能去那么拥挤的地方。 总待在家里也是不可能的,待久了会闷的。于是下午稍微收拾了下便去了江对岸溜达了起来。看了看复兴岛一个下午也就过去了。这地也不是啥可能热闹的地,一路上冷冷清清的,都没见到啥人,也就岛上的海警部队的训练声音嘹亮。 后面几天基本也就这节奏了。一天逛,一天家里蹲。把杨浦区走了不少。原本我觉得我这个地已经算是人口稠密了,但是和它那里一比,还是差远了。现在总算是知道人家这为啥算市中心了。 中途还去了一趟医院,赶个大早去了。本打算在那边吃个早餐的,谁知道过去旁边的一排都关门了,真的是,这是都不挣钱了吗?跑了三公里,到一个地铁口旁边,以为那边吃的会多点,谁知道也是毛都没有。没办法,只好到全家去买我刚刚问过的还要20分钟才熟的包子。虽然很难吃,也只好将就了。 中午去了趟之前住过的蓝村路,那个地吃的多,打算在这里好好补一补早上没吃好的胃口。走了一条街,也是没找到好吃的开门 的店。生意好的都回家过年了。匆匆在旁边的老盛兴对付了一口就回去了。 下午饿了的时候,总算是好好的满足了自己一把。弄了两个老好吃的外卖,还是外卖靠谱了。牛肉板面实的我老家大新野的真传,汤,炸辣椒,和面都很正宗,味道好极了,就是老板的包装有点次,面都有点跎一起了,但就这样也是极满足了。胡子大厨也是一如既往的好。 假期后面我还去寻找这家板面店,去吃下没有跎的板面。找到这家店发现是个专门的外卖店,店里面几乎没有坐的地,没怎么考虑也就放弃了。下次想吃还是外卖了。 春节期间倒也干过两个和技术有关的事。一个是根据github的开源项目最终飞机的行踪的,这个就干了一半,还有点小问题,后面有空再看吧。另外一个就是把自己的blog从wordpress迁移到了hugo。 出发点呢就是wordpress太慢了,实在是太慢了。hugo用起来太省力,而且就blog而已功能足够,还加载快。中间最头痛的是迁移历史文章,虽然咱也没多少文章,但是wordpress的到处md的插件总是死掉,中间真的是让人很崩溃,搞得人心情都很不爽。 终究还是人肉迁移了,也就是文章不多,就这也搞了差不多8个小时。上班我也没有这么敬业。从晚上搞到凌晨4点多,就这还有点收尾是放到了中午干的。整个生物钟都弄颠倒了。假期的后面两天都在为怎么把这个作息调整好而难受。 过年期间也没啥好剧让人看,看了一部下线好久的我和我的父辈。真的也就第一段吴京的戏份让人惊艳,后面的几段都让人有点昏昏欲睡。再有就是又看了童年鬼畜剧,西游记后传。最近抖音总给我推荐,剪的也吸引人。爬了下种子,看了起来,还是老剧有滋味。 假期的收尾是以一顿海底捞结束的。以火锅始,以火锅终。最后一天还是在杨浦逛的,黄兴公园是足够大的,人工湖旁边大爷大妈们载歌载舞,好不乐哉。这里也是小朋友的乐园,旁边的人造沙滩,到处都是玩沙的。还有人在这里打沙滩羽毛球。 海底捞吃饭的时候是春节期间最难受的时候,里面可能是太暖和了,导致我困意十足,生物钟大概还没恢复的缘故,头也有点蒙,吃起来是完全没有胃口,也算是省了点钱。 最难受的时候都打算吃完打车回家了,但一出商场,冷空气一吹,还是地铁回去,毕竟省钱。18-6简直了,这换乘区间赶的上徐家汇了,我说怎么工作日没啥人在这里换乘呢。 晚上回去,一夜虚汗,倒也是睡了不少时间,睡眠完全恢复了,体力也正常了,也迎来了工作日。

2022-02-07 16:08 · 1 min · 江波·林沂