方法 wait()
是让当前执行代码的线程等待,wait()
是 Object 类的方法。在调用 wait()
方法前,线程需要获得对象级别锁,只能在同步方法或者同步块中调用,执行 wait()
方法后,当前线程释放锁。如果调用时没有持有适当锁,会抛出 IllegalMonitorStateException 异常。
方法 notify()
也需要在同步方法或者同步块中调用,同样调用前也需要获取对象锁。如果调用没有持有适当的锁,也会抛出 IllegalMonitorStateException 异常。notify()
方法永安里通知可能处于等待该对象锁的其他线程,如果有多个线程等待,由线程规划器随机挑选一个呈现 wait 状态的线程,发出 notify 通知,并使它获得该对象的对象锁。notify()
方法执行后,当前线程不会马上释放该对象锁,wait 状态的线程也不能马上获取该对象锁,需要等执行 notify()
方法的线程将程序执行完,也就是退出 synchronized 代码块之后,当前线程才会被释放锁。
如果发出 notify()
操作时没有处于阻塞状态的线程,命令会被忽视。
wait()
方法使线程停止运行,而 notify()
使停止的线程继续运行。
如果主线程要等待子线程执行完成之后结束,可以使用 join() 方法。
join(long)
在内部使用 wait(long)
方法实现,所以会释放锁。而 Thread.sleep(long)
方法不会释放锁。
ThreadLocal 类主要解决的就是每个线程绑定自己的值,每个线程都有自己的私有数据。
公平锁线程在获取锁的顺序是按照线程加锁的顺序来分配的,即先来先得 FIFO ,而非公平锁就是获取锁的抢占机制,随机获的锁。
类 [[ReentrantLock]] 是完全互斥排他,同一时间只有一个线程能够执行 ReentrantLock 后任务,这样的方式保证了实例变量的线程安全,但是效率低下。所以 JDK 中提供了另外一个读写锁 ReentrantReadWriteLock ,在某些不需要操作实例变量的方法中,可以使用读写锁 ReentrantReadWriteLock 来提升方法的效率。
读写锁表示有两个锁,一个读相关锁,也成为共享锁,另一个是写相关的锁,也叫排它锁。读锁之间不排斥,写锁与其他锁互相排斥。多个线程可以同时读操作,但是同一时刻只允许有一个线程写操作。
NextCloud 支持 WebDAV 协议,用户可以完全通过 WebDAV 来连接并同步文件。虽然官方还是推荐 使用客户端来同步文件,不过如果要临时访问 NextCloud 上的文件,使用 WebDAV 方式还是很便捷的。
假设 NextCloud 的地址是 example.com 这个,那么在 Linux 下,一般文件管理器中有连接到服务器的选项在其中,填入服务器 IP 地址,访问端口,然后访问地址填写 /remote.php/dav/files/[USERNAME]
输入该用户的用户名和密码即可访问该用户的所有文件列表。
如果要直接在文件管理器中访问,可以尝试使用如下的协议地址:
dav://[USERNAME]@[SERVER_IP]:[PORT]/remote.php/dav/files/[USERNAME]
在 Linux 下还能通过命令行访问,具体可参考下面的链接。
同步地址,其中 ip, port, username,需要替换:
http://ip:port/remote.php/dav/files/username/JoplinSync
今天突然遇到一个问题,使用手机拍摄的照片 5+M 体积巨大,但是网易要求的图片大小需要小于 1M,所以就有了压缩图片的需求。记得很久以前使用过 TinyPNG 这个服务,但是唯一一点不好的就是无法脱离他在线的服务,需要把照片上传到他的网站上才能进行压缩。虽然有 tinypng-cli 这个命令行的工具,但其实也是依赖在线服务的。所以就找了一下,然后发现了 jpegoptim
和 optipng
这两个工具。
安装
apt-get install jpegoptim
使用
jpegoptim file.jpg
然后使用 du -h file.jpg
查看文件大小。使用这种方式 jpegoptim 会尽量使用无损失的压缩方式,所以几乎看不出区别。而如果想要指定大小,比如想要压缩到 500k 大小,可以
jpegoptim --size=500k file.jpg
而如果要批量压缩,在目录中 jpegoptim *.jpg
即可。
如果要将 EXIF 信息移走可以添加参数
jpegoptim --strip-exif file.jpg
结合 find
find images_folder/ *.{jpeg,jpg} -exec jpegoptim {} \;
安装
apt-get install optipng
使用
optipng file.png
结合 find
find images_folder/ *.png -exec optipng {} \;
优化 jpeg 压缩算法
命令行版本
安装方式:
npm install -g mozjpeg
mozjpeg --help
macOS 下有一个不错的工具叫做 imageOptim
安装:
brew install imageoptim-cli
优化当前目录中的 PNG:
imageoptim --imagealpha '**/*.png'
优化 JPG:
imageoptim --jpegmini '**/*.jpg' '**/*.jpeg'
今天在看 Kafka 源码 LongSerializer
时看到将 Long 型转 byte 数组的实现,感觉需要补习一下位运算符 (bitwise operator),所以有了这篇。
Java 提供的位运算符有:
<<
)、右移 ( >>
)<<<
)、无符号右移 ( >>>
)&
)|
)~
)^
)除了位非 ( ~
) 是一元操作符外,其它的都是二元操作符。
与或非,亦或 就不说了。
左移 1 位 (<<1
) ,值乘 2,以后依次乘 2.
右移 1 位 (>>1
),值除以 2。
对于负数,二进制高位为 1,所以一个 int 类型的 -5
二进制表示是
1111 1111 1111 1111 1111 1111 1111 1011
对于负数,使用右移 >>
时,则高位补 1,而对于无符号右移,则高位补 0 。
由位运算操作符衍生而来的有:
&=
按位与赋值|=
按位或赋值^=
按位非赋值>>=
右移赋值 a »= 1 就是 a = a » 1<<=
赋值左移>>>=
无符号右移赋值和 +=
一样,理解为 a += 1 也就是 a = a + 1。
python -m SimpleHTTPServer
python -m http.server
echo '<json string>' | python -m json.tool
python -c "import paramiko"
源码安装
python setup.py install
pip 子命令
子命令 | 说明 |
---|---|
search | 搜索 pip search flask |
install | 安装 pip install flask==0.8 , pip install -r requirements.txt |
uninstall | 卸载 |
show | 查看包详情 |
check | pip 9.0.1 之后提供,检查包是否完整 |
list | 列出已安装 |
freeze | 导出已安装包列表 pip freeze > requirements.txt |
completion | 生成命令补全配置 pip completion -z >> ~/.zshrc && source ~/.zshrc |
下载时指定
pip install -i https://pypi.douban.com/simple/ flask
或者创建 ~/.pip/pip.conf
,写入
[global]
index-url = https://pypi.douban.com/simple/
威联通的机器本来就是基于 Linux 定义的,所以想要定时任务就会想到 crontab,在威联通中使用 crontab 必须使用 SSH 登录。
然后基本使用 crontab -l
查看当前 qnap 中已经存在的定时任务。
在大多数桌面版 Linux 中会使用 crontab -e
来编辑 crontab 配置,但是注意不要在威联通中使用这种方法,威联通在重启的时候会覆盖使用这种方式写入的配置。如果想要永久的保存配置,应该使用
vi /etc/config/crontab
然后写入配置,比如
0 4 * * * /share/custom/scripts/custom1.sh
这行配置表示在 凌晨 4 点执行后面的脚本。
或者直接使用 echo,将命令放到双引号中
echo "1 4 * * * /share/custom/scripts/custom1.sh" >> /etc/config/crontab
另外需要注意可执行文件一定需要可执行权限 chmod +x filename.sh
重启 crontab
crontab /etc/config/crontab && /etc/init.d/crond.sh restart
定时任务 | 解释 |
---|---|
0 3 * * 0 /etc/init.d/idmap.sh dump | |
10 15 * * * /usr/bin/power_clean -c 2>/dev/null | |
0 4 * * * /sbin/hwclock -s | http://linux.die.net/man/8/hwclock |
0 3 * * * /sbin/vs_refresh | |
0 3 * * * /sbin/clean_reset_pwd | |
0-59/15 * * * * /etc/init.d/nss2_dusg.sh | |
30 7 * * * /sbin/clean_upload_file | |
0-59/10 * * * * /etc/init.d/storage_usage.sh | |
30 3 * * * /sbin/notice_log_tool -v -R | |
*/10 * * * * /sbin/config_cache_util 0 | |
0-59/20 3 * * * /sbin/adjust_time | |
0 8 * * * /usr/local/medialibrary/bin/mymediadbcmd buildall 1>/dev/null 2>/dev/null | |
55 9,21 * * * /sbin/notify_update -s -p 1>/dev/null 2>&1 | |
0 23 */1 * * /sbin/qpkg_cli -U 1>/dev/null 2>/dev/null | |
0 0 * * * /share/CACHEDEV1_DATA/.qpkg/Qcenter/qnap-cms/bin/log_retention.sh > /dev/null | |
0 0 * * * /share/CACHEDEV1_DATA/.qpkg/Qcenter/qnap-cms/bin/nasconfig_retention.sh > /dev/null | |
0 2 * * * /sbin/qfstrim | |
0 0 * * 0 /sbin/storage_util –data_scrubbing raid_id=-1 >/dev/null 2>&1 | |
51 * * * * /sbin/qddns_check 2>/dev/null | |
* * * * * /var/cache/netmgr/lock_timer.sh | |
* * * * * /var/cache/netmgr/detect_defaultgw_internet.sh | |
0 4 * * * /etc/init.d/wsd.sh restart | |
4 3 * * 3 /etc/init.d/backup_conf.sh | |
0 0 * * * /etc/init.d/antivirus.sh archive_log | |
56 0 */1 * * /etc/init.d/antivirus.sh update_db | |
20 08 * * * /mnt/ext/opt/QcloudSSLCertificate/bin/ssl_agent_cli | |
35 7 * * * /sbin/qsyncsrv_util -c > /dev/null 2>/dev/null | |
0 0 * * * /sbin/qsyncsrv_tool –fix > /dev/null 2>/dev/null |
curl -X GET \
'https://frodo.douban.com/api/v2/group/622198/topics?count=30&sortby=new&os_rom=android&apikey=0dad551ec0f84ed02907ff5c42e8ec70&channel=Google_Market&udid=5e4159565b89f86cccda&_sig=YWtLhd6UEq%2Bh7xDWs%3D&_ts=1529656502' \
-H 'Cache-Control: no-cache' \
-H 'Host: frodo.douban.com' \
-H 'User-Agent: api-client/1 com.douban.frodo/5.26.0(134) Android/23 product/OnePlus3 vendor/One model/ONE rom/android network/wifi'
python
import requests
url = "https://frodo.douban.com/api/v2/group/622198/topics"
querystring = {"count":"30","sortby":"new","os_rom":"android","apikey":"0dad2907ff5c42e8ec70","channel":"Google_Market","udid":"5e3fff058b89f86cccda","_sig":"YWtLhDWs%3D","_ts":"1529656502"}
headers = {
'User-Agent': "api-client/1 com.douban.frodo/5.26.0(134) Android/23 product/OnePlus3 vendor/One model/ rom/android network/wifi",
'Host': "frodo.douban.com",
'Cache-Control': "no-cache",
'Postman-Token': "1c40a79a-90ba-6d85aeb074e8"
}
response = requests.request("GET", url, headers=headers, params=querystring)
print(response.text)
NextCloud 算是很重度 的使用起来了,VPS 上安了,NAS 上也有。各个平台使用体验非常不错,不过唯一一点缺憾是有些时候 Ubuntu/Mint 上 NextCloud 随机启动之后托盘消失,导致看不到同步进度,老是让我感觉没有启动。
所以为了修复这个问题,需要完成以下两个步骤。第一个步骤就是在 startup applications 中将 NextCloud 设定延迟 10s 启动。
第二步就是需要卸载 appmenu-qt5
这个 bug 可以参考这个 issue
sudo apt remove appmenu-qt5
Java 版本
sh zkCli.sh -server IP:port
进入 server 连接后使用
ls /
来查看节点包含内容
ls2 /
说明:
ls -s
代替。create 创建新的 Znode 节点,path:路径 data:数据 acl:权限,不指定默认为 world:anyone:cdwra
create /test "mydata"
该命令其他选项:
-s
: 顺序节点-e
:临时数据节点,重启会消失get /test
在 get 命令的结果中会输出其他信息
set /test "new data"
delete /test
rmr /test
listquota
ZooKeeper -server host:port cmd args
addauth scheme auth
close
config [-c] [-w] [-s]
connect host:port
create [-s] [-e] [-c] [-t ttl] path [data] [acl]
delete [-v version] path
deleteall path
delquota [-n|-b] path
get [-s] [-w] path
getAcl [-s] path
history
listquota path
ls [-s] [-w] [-R] path
ls2 path [watch]
printwatches on|off
quit
reconfig [-s] [-v version] [[-file path] | [-members serverID=host:port1:port2;port3[,...]*]] | [-add serverId=host:port1:port2;port3[,...]]* [-remove serverId[,...]*]
redo cmdno
removewatches path [-c|-d|-a] [-l]
rmr path
set [-s] [-v version] path data
setAcl [-s] [-v version] [-R] path acl
setquota -n|-b val path
stat [-w] path
sync path
Apache [[ZooKeeper]] 是 Apache 软件基金会的一个软件项目,为大型分布式计算提供开源的分布式协调系统,提供的功能包括配置服务、同步服务和命名注册等。Zookeeper 项目的初衷就是为了降低分布式应用从头开发协同服务的负担。
ZooKeeper is a high-performance coordination service for distributed applications. It exposes common services - such as naming, configuration management, synchronization, and group services - in a simple interface so you don’t have to write them from scratch. You can use it off-the-shelf to implement consensus, group management, leader election, and presence protocols. And you can build on it for your own, specific needs.
基本功能也如上述所说可以概括成:
通常实际使用场景比如管理 HBase 集群,配置管理,和 Kafka 配合等等,Zookeeper 设计更专注于任务协作,并没有提供任何锁的接口或通用存储数据接口。
Zookeeper 不适合用来作为海量存储,对于大量数据的存储应该考虑数据库或者分布式文件系统。
Zookeeper 提供的命名空间通常是 /
开头,并且有着明确的等级管理。
Zookeeper 命名空间中的每一个节点(node)都包含一组数据,子节点亦然。可以想象成文件系统中的目录,但是这个目录同样也有数据。Zookeeper 被设计用来保存协同数据,包括状态信息,配置,位置信息,等等,所以数据通常很小,bytes 到 kilobyte 大小。通常把这些节点叫做 znode。
Znodes 维护一个结构,包含数据变化版本号,ACL 变化,时间戳,cache 验证等。每一个节点都拥有 Access Control List(ACL) 限制谁可以访问。Znode 的版本号随着数据变化而递增。
ZooKeeper 数据节点类型:
服务器节点类型
服务端选举算法 Paxos 类似 客户端通信方式 JAVA-NIO
ZooKeeper 服务器端运行于两种模式下:standalone 和 quorum。
选举算法,类似 [[Paxos 算法]]
ZKReentrantLock lock = new ZKLock(zk,timeout,sessionManager);
lock.lock();
....... your thing
lock.unlock();
ZAB 协议(Zookeeper Atomic Broadcast)是为分布式协调服务 ZooKeeper 专门设计的一种支持崩溃恢复的原子广播协议。在 ZooKeeper 中,主要依赖 ZAB 协议来实现分布式数据一致性
quorum:集群中超过半数的节点集合
ZAB 中的节点有三种状态:
节点的持久状态
Zab 可以满足以下特性
follower 要么 ack,要么抛弃 Leader,因为 zookeeper 保证了每次只有一个 Leader。另外也不需要等待所有 Server 的 ACK,只需要一个 quorum 应答就可以了。
两种模式,分为 broadcast 模式(广播模式,同步)和 recovery 模式(恢复模式,选 leader)
为了保证事务的顺序一致性,ZooKeeper 采用了递增的事务 id 号(zxid)来标识事务。所有的提议(proposal)都在被提出的时候加上了 zxid。实现中 zxid 是一个 64 位的数字,它高 32 位是 epoch 用来标识 leader 关系是否改变,每次一个 leader 被选出来,它都会有一个新的 epoch,标识当前属于那个 leader 的统治时期。低 32 位用于递增计数。
每个 Server 在工作过程中有三种状态:
Follower 收到 proposal 后,写到磁盘(尽可能批处理),返回 ACK。
Leader 收到大多数 ACK 后,广播 COMMIT 消息,自己也 deliver 该消息。
Follower 收到 COMMIT 之后,deliver 该消息。
leader 奔溃或者 leader 失去大多数 follower 时,zk 进入恢复模式,恢复