报名链接
在浙北的一隅山间,
就藏着一座梅花生态博物馆!
千亩梅园嫁接了东方红梅、
绿萼梅等品种,
漫山遍野盛开的梅花倏然出现在眼前,
站在288米高的玻璃桥上
全方位赏1000亩梅花
那才叫一个美不胜收嘞~
让我们一起, 去找寻这个季节最美的梅花!
每年的2-3月,就是原乡小镇一年一度的梅花节。瀛洲梅园的梅花开得正盛,一树树,一朵朵,绽放着初春的美好,梅园花影交错,或素雅疏淡,或热烈曲折,气韵灵动,别致雅趣,与山野相互映衬,美不胜收,吸引无数摄影师前往。
瀛洲梅园俗称千亩梅园,拥有近万棵青梅,萦绕在枝头的暗香如潮,绵延数十里,惹人驻足沉醉。
这里有沿山势建有长三角地区最长的梅林观光木栈道,总长约为4.8公里,并设有12座观梅亭,堪称为湖州的生态梅花博物馆,自在漫步细品姿态各异,颜色万千的梅花朵朵开。
穿上汉服赴原乡闹春赏梅之约,各地汉服同袍雅集,欢聚“西塞山梅花汉服节”,在粉墙黛瓦的花海中漫享古典时光。
聚焦非遗,经典传承。琳琅满目的非遗手工物品,香包、剪纸、糖画、竹编等,这回可是把各种“老古董”,全都给你搬来原乡咯~
喜欢萌宠,是孩子的天性,给孩子一次撒欢的机会!摸摸小鹿柔软的毛毛,鼓励小朋友主动投食小奈良,与动物亲密接触,触发孩子的爱心,大人也可以在这里找到自己久违的童心。
5D酷炫的玻璃桥,全长有288米,全透明的玻璃设计,脚踩到哪,哪里就会裂开,在进行惊心动魄的挑战的同时,你还可以俯瞰远观香气袭人的梅花“雪海”,欣赏一场梦幻的视觉盛宴。
这里有亚洲规模最大、种类最多的,蝴蝶生态科普体验馆,可以了解蝴蝶的生活、习性、分布,参与蝴蝶标本的制作。
这里有可爱的复古小火车,1500米的轨道,7min的童话探险,迎着春风哐当哐当,坐着小火车转悠一圈就沦陷了。
除了上面这些,还有滑翔伞、ATV越野、童心童趣园、骑马、射箭、蹦蹦云乐园、粉色沙滩…
这周六要去临安窑头山徒步, 春节末尾的时候团队的几个成员已经探过一次路。当时雪已经有到人脚踝那么厚了,最近今天临安依旧是大雪,等到我们徒步的时候,山上的雪应该会很厚了。
临安今日雪景
探路回来,同伴已经决定此次徒步要让大家都带上雪爪。我虽然已经徒步好几年了,但是之前去的山上都是没什么雪的,所以这玩意我也是没准备过。疫情原因,也是好久没爬了。之前的背包,登山杖什么的丢的丢,坏的坏,这次一起去置办了去。
总计需要以下几样东西,下班后一起迪卡侬置办了。
登山包。这次打算搞个小点的,之前的30升实在太大了,咱也没有要背帐篷的需求。
登山杖。要准备两根了,雪这么大,还是两个牢靠点。
手套。下雪天还要弄个好的,要不手太冷。用手套堆起雪人来也不冻手。
雪爪。这玩意一年用不了两次,不过这么大的雪还要准备一个的。
头灯。说来惭愧,徒步3年了,算是半个领队了,竟然没准备。这次八成下山天要黑,搞一个了。
手机背包夹。打算沿路用手机录个像,用它可以解放双手,要是感觉好,后面可以弄个专业的录像设备。这玩意也不知道迪卡侬有没有。
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 为了优化我们的代码,它还会进行指令重排!一行代码可能不单单只有一个指令呀,就是这个指令重排让我们原本有序的代码变成了无序的指令,所以可能会出现安全问题。
而我们的 volatile 就可以通过添加内存屏障来保证指令的安全有序,具体来说就是它确保指令重排序时不会把其后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面;即在执行到 volatile 关键字的时候,在它前面的操作已经全部完成;同时它又是拒绝 JIT 的,所有的改动会同时被所有的线程看到。
内存屏障会提供3个功能:
确保指令重排序时不会把其后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面;即在执行到内存屏障这句指令时,在它前面的操作已经全部完成;
强制将对缓存的修改操作立即写入主存;
如果是写操作,它会导致其他CPU中对应的缓存行无效。
JMM具备一些先天的有序性,通过Happens-Before原则就可以保证的一定的有序性。
问:volatile能保证原子性吗。参考:VOLATILE 只保证可见性,并不保证原子性
Volatile实现内存可见性是通过store和load指令完成的;也就是对volatile变量执行写操作时,会在写操作后加入一条store指令,即强迫线程将最新的值刷新到主内存中;而在读操作时,会加入一条load指令,即强迫从主内存中读入变量的值。但volatile不保证volatile变量的原子性,例如:...
Duboo核心能力 面向接口代理的高性能RPC调用 提供高性能的基于代理的远程调用能力,服务以接口为粒度,为开发者屏蔽远程调用底层细节。
智能容错和负载均衡 内置多种负载均衡策略,智能感知下游节点健康状况,显著减少调用延迟,提高系统吞吐量。
服务自动注册和发现 支持多种注册中心服务,服务实例上下线实时感知。
高度可扩展能力 遵循微内核+插件的设计原则,所有核心能力如Protocol、Transport、Serialization被设计为扩展点,平等对待内置实现和第三方实现。
运行期流量调度 内置条件、脚本等路由策略,通过配置不同的路由规则,轻松实现灰度发布,同机房优先等功能。
可视化的服务治理与运维 提供丰富服务治理、运维工具:随时查询服务元数据、服务健康状态及调用统计,实时下发路由策略、调整配置参数。
Dubbo2与Dubbo3的区别 dubbo2的服务注册是基于接口的,dubbo3的服务注册时基于应用的,这会带来几点好处。首先,对于注册服务来说,其的负载将会降低很多,因为接口比应用至少是多了一个数量级的;其次,对于服务治理来讲,常见的情景是屏蔽某个应用的在某个实例上的所有接口,这种情景下,基于应用的注册显而易见更好处理。当然,由于dubbo3为了dubbo2可以更好的平滑迁移,默认还是基于接口注册的。
前几天个人网站从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> 这样一波下来,完美解决我的图片描述不显示的问题。有相同需求的同学都可以用我这种方式试试。