个人笔记软件的选择
写这篇文章的目的, 主要是为了记录一下自己使用的笔记软件的过程以及最终选择(当然也只是目前的选择, 后续会不会变就不清楚了), 给其他同样有此问题的人一个参考。 先说一下本人选择笔记软件的一些原则: 数据要掌握在自己手上,放在云上的我感觉都不安全, 因为开发该软件的公司哪天收费或倒闭了, 你自己的数据就没了或者不好弄出来 要多端都能使用 方便同步 最好能自己部署 为知笔记推荐星级:★ 这是我个人早起用的时间比较长的一个笔记软件, 是一个传统的笔记软件, 使用过程中陆陆续续出现过一些问题, 后来为知强制收费, 加上对其富文本格式的担心,花了一天的时间把数据都迁移出来了。 为知笔记有一个官方的docker镜像, 可以自己部署使用, 但是有些功能还是需要连接到官方使用, 所以不是很友好。 最终弃之。 typora + 坚果云推荐星级:★★★ 在不使用为知笔记之后, 我一直在寻找替代品, 包括印象笔记,有道笔记等, 但都不符合预期, 且不符合数据掌握在自己手中的原则。在这个过程中,了解到了markdown这一文本格式, 就迅速的爱上他了。 再结合数据同步与备份, 便使用了 typor...
ConcurrentHashMap源码分析
ConcurrentHashMap的实现机制是一直在变化的, 其中8的变化较大, 下面分别说明一下在Java7和Java8中他们的实现机制。 Java 7 实现原理主要是基于分离锁来实现的。这样做的目的是, 在进行并发操作的时候, 只需要锁住相应的Segment, 而不需要去锁住整个数据, 提高并发性能。 存储数据的是一个个的Segment,Segment是继承自ReentrantLock,所以它本质上就是一个锁。 每个Segment内部都有一个HashEntry的数组, 这个HashEntry数组存储方式和HashMap内部的table数组类似, 哈希相同的元素也是以链表形式存储。 get在并发的时候,get操作只要能保证可见性即可, 所以没有同步操作。 定位元素所属的segment 利用jdk提供的Unsafe方法保证以可见性的方式获取元素,UNSAFE.getObjectVolatile() put 利用UNSAFE.getObject() 方法获取元素所属的segment 利用所属的segment获取可重入锁,从而将该segment锁住, 防止其他的线程进行并发写 ...
HashMap源码分析
基本原理HashMap是由数组Node<K,V>[] table 和链表(或者树)组成的一个复合结构。 数组被分成一个个的桶(buket),通过下面的这个算法决定元素在桶中的位置: 12// n为数组长度,hash为key的哈希值p = tab[i = (n - 1) & hash] 若p相同,则以链表形式存储。当链表长度超过阈值(TREEIFY_THRESHOLD=8)时,则将链表转换为红黑树。 此处为什么需要这么做? 主要是基于查询的效率考虑。链表查询元素的时间复杂度为O(n),随着链表长度的增大,查询时间也会递增。而红黑树的时间复杂度为O(logn),此处是一个以空间换时间的典型案例。 HashMap中几个特殊值说明: initialCapacity:HashMap初始容量,默认为16 loadFactor:负载因子,默认0.75 threshold:键值对数量的最大值(不是table数组的长度),超过这个值,则需要扩容,会变为原先值的两倍 TREEIFY_THRESHOLD:链表转换红黑树阈值,默认为8, 当超过该值时, 链表就会转换为...
java大图片压缩与裁剪时防止oom
常规使用java进行图片裁剪或压缩的时候, 比如使用ImageIO.read()读取图片信息的时候, 或者使用Thumb nails框架进行压缩时, 都会调用DataBufferByte类的下面这个方法: 12345678910public DataBufferByte(int size, int numBanks) { super(STABLE, TYPE_BYTE, size, numBanks); bankdata = new byte[numBanks][]; for (int i= 0; i < numBanks; i++) { // 构造数组 bankdata[i] = new byte[size]; } data = bankdata[0];} 当图片像素很大时, size的值会很大, 此时构造这个数据就有可能会出现oom,比如当一张6.4M的图片, 宽高是5472*7296, size的值是114M。 基...
arthas中如何获取Bean
现在大部分应用都是通过Spring来管理对象, 在使用arthas分析线上问题时, 如何获取Spring中已经注入到容器中的Bean, 主要是使用tt命令。 首先执行如下命令,等待输出 1tt -t org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter invokeHandlerMethod -n 3 假设要搜索的类名为com.example.DemoService, 注意此处需要使用类的全限定名。 1tt -i 1000 -w 'target.getApplicationContext().getBean("com.example.DemoService").getTargetSource().target'
arthas的一些使用技巧
arthas获取spring中的bean现在大部分应用都是通过Spring来管理对象, 在使用arthas分析线上问题时, 如何获取Spring中已经注入到容器中的Bean, 主要是使用tt命令。 首先执行如下命令,等待输出 1tt -t org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter invokeHandlerMethod -n 3 假设要搜索的类名为com.example.DemoService, 注意此处需要使用类的全限定名。 1tt -i 1000 -w 'target.getApplicationContext().getBean("com.example.DemoService").getTargetSource().target' arthas获取http请求的入参和出参有时我们需要线上跟踪某个请求的入参和出参, 此时可以使用arthas的watch命令。 基于spring的工程,所有请求都会走Requ...
Linux中文件权限说明
概述 Linux下的文件权限包括读, 写, 执行, 英文简写分别是 r, w, x 文件权限包含三个方面: 拥有者, 用户组, 其他组。每个文件可分别对这三个方面设置不同的rwx权限。通常情况下,一个文件只能归属于一个用户和组, 如果其它的用户想有这个文件的权限,则可以将该用户加入具备权限的群组,一个用户可以同时归属于多个组。 查看文件权限ls -l 输出格式如下: -rw-r--r-- 1 root root 25934 Jun 26 10:35 X120 其中第一列除了第一个表示文件类型外, 剩下9个则表示该文件在上面三个粒度下的权限,具体信息 2,3,4列表示文件所有者权限 5,6,7列表示该文件所属用户组的权限 7,8,9列表示其他组的权限 更改文件权限chmod命令, 其参数如下: -R 以递归的方式对目前目录下的所有档案与子目录进行相同的权限变更 下面只介绍一下使用数字来表示的权限使用方法。 基本规定如下: 4 读r 2 写w 1 执行x 其他的权限组合用这几个进行相加就行, 示例如下: 7 可读+可写+可执行 rwx (4+2+1=7...
Shell语法参考
几点注意事项 一次执行多条命令,可以有如下三种方法, 其区别如下: 分号: 顺序地独立执行各条命令, 彼此之间不关心是否失败, 所有命令都会执行 && : 顺序执行各条命令, 只有当前一个执行成功时候, 才执行后面的 || : 顺序执行各条命令, 只有当前面一个执行失败的时候, 才执行后面的 设置shell脚本遇到错误时自动退出, 不执行后续命令 1#!/bin/bash -e 或者 set -e 特殊符号使用12345678910> 覆写原先的内容>> 在原先的内容后追加$? 前一个命令或者函数的返回码, 0表示执行成功$1 表示第一个参数,$2 表示第二个$# 命令行参数的个数$0 当前程序的名称$* 以"参数1 参数2 ..."的形式保存所有参数$ 本程序进程PID$! 上一个命令的PID脚本内取得输入命令时的参数: $n n代表第几个参数 特殊文件 /dev/null 重定向到此文件的数据都会被系统丢掉 /dev/tty 自动重定向到一个终端 函数使用 ...
Linux常用命令参考
当做个人字典使用, 会进行不定期更新! tar打包与压缩命令。 常用参数: -c (–create) 建立新的备份文件 -x (–extract) 从备份文件中还原文件 -z (–gzip或–ungzip) 通过gzip指令处理备份文件 -v (–verbose) 输出执行过程中的详细信息 -f (–file) 指定备份文件 12345# 将/home文件夹下所有内容打包压缩成home.tar.gz文件tar -czvf home.tar.gz /home# 将home.tar.gz文件解压到当前目录tar -xzvf home.tar.gz getops该命令可以用来解析命令行参数。 以下表示获取命令行参数 -d -t的值 1234567891011while getopts 'd:t:' OPT; do case $OPT in d) echo "d $OPTARG" exit 0;; t) echo "t $OPTARG";; ?) ...
docker安装confluence
自己搭建一个confluence wiki,现记录一下搭建过程和其中需要注意的点。 编写docker-compose12345678910111213141516171819202122232425version: '3'services: db: image: postgres:latest container_name: confluence-db ports: - "15202:5432" restart: always environment: - POSTGRES_PASSWORD=123456 volumes: - /opt/docker/confluence/pgsql-data:/var/lib/postgresql/data confluence: image: cptactionhank/atlassian-confluence:latest container_name: confluence ports: - "...




