red blue yellow green    2017-05-07 22:44:55    221    0    0
## 截取字符串的最后一位 ``` bash # echo $var 3234j35ja # echo ${var: -1} #注意:-1前要有个空格 a ``` ## 来自网络 1. 很多很全很强大的http://tldp.org/LDP/abs/html/contributed-scripts.html ## 参数校验 ### 校验参数个数 ``` bash #!/bin/sh #-
2017-05-06 15:41:17    312    0    0
> Linux中diff命令的功能为逐行比较两个文本文件,列出其不同之处。它对给出的文件进行系统的检查,并显示出两个文件中所有不同的行,不要求事先对文件进行排序 ## 命令使用 ``` bash diff [OPTIONS] files ```
2017-04-25 12:25:13    205    0    0
## OR ### 使用`\|`
2016-11-27 00:12:20    540    0    0
# 三种查询方式 Influxdb提供了三种方式支持查询:HTTP接口,命令行(CLI),客户端类库。
2016-11-26 23:58:47    520    0    0
## 先说结论 golang中,值类型在作为方法参数和方法的接受者的时候,都需要进行值的拷贝,所以,使用值类型的时候要多加注意。 对于方法的接受者,如果方法需要修改接受者的某个变量值,那么就应该把接受者设计成pointer receiver,否则对于receiver变量的修改将无效。 ## 问题由来 今天群里有人发了下面的代码: ``` go type data struct { sync.
2016-11-21 23:02:50    540    0    0
#启动influxdb server `service influxd start` 或直接`influxd` #数据库操作 ## create db `CREATE DATABASE {dbname}` dbname可以是任意的unicode字符串,但需要放在引号里面,如果只包含ascii码,可以不用引号 ## 显示所有数据库 `show databases` 新安装的influxdb会默认创
java基础    2016-06-21 20:51:29    426    0    0

问题由来

今儿不小心在群里看到一位朋友发了下面的代码:
title
通过输出可以看到,这段代码的作用是把驼峰命名格式的字符串替换成下划线分割,这个功能比较简单,但是吸引我的却是他的代码。

  1. "createTime".replaceAll("([A-Z]+)","_$1")

这行代码其实很简单,就是调用了String类的replaceAll方法,方法的第一个参数是正则表达式,第二个参数是将要被替换成的新值。让我惊奇的是他代码中,replaceAll的第二个参数,也就是JDK文档中名为replacement的参数,竟然是”_$1”,这是什么鬼?还支持类似占位符这样的东西?我一直都不知道。。

问题探索

由于之前研究过一段正则表达式,通过观察replaceAll的第一个参数([A-Z]+),我猜想,这个应该是用到了正则表达式的分组,对应JDK中,就是java.util.regex.Matcher类的group()方法。
于是看了下String.replaceAll方法是如何实现的。
JDK源码如下:

  1. public String replaceAll(String regex, String replacement) {
  2. return Pattern.compile(regex).matcher(this).replaceAll(replacement);
  3. }

哦,原来它底层就是用了Matcher,只不过用的是Matcher自己的replaceAll方法。
去看它的文档:
title

原来这个方法的参数果然有鬼,看下实现代码:

  1. public String replaceAll(String replacement) {
  2. reset();
  3. boolean result = find();
  4. if (result) {
  5. StringBuffer sb = new StringBuffer();
  6. do {
  7. appendReplacement(sb, replacement);
Redis NoSQL    2016-06-19 00:58:32    399    0    0

Redis事务的实现

  1. redis的事务通过MULTI,EXEC,WATCH,DISCARD等命令实现。
  2. Redis通过MULTI命令开启事务,通过EXEC提交事务,通过DISCAR放弃事务
  3. Redis事务执行的结果会按顺序返回给客户端。
    Redis事务一般包含三个阶段
    1)开始事务
    2)命令入队
    3)事务执行

开始事务

通过MULTI命令开始事务,MULTI命令把执行该命令的客户端从非事务态转为事务态。该命令服务端始终返回OK

命令入队

开启事务之后,客户端向服务端发送的命令不会被立即执行,服务端会将这些命令放入一个事务队列,同时响应给客户端QUEUED。

命令执行

客户端向服务端发送EXEC命令之后,服务端事务队列中的事务会被按顺序执行 ,最后执行命令所得结果全部返回客户端 。

Redis事务的特性

数据库事务的ACID特性在Redis中是否都满足呢?

原子性

Redis事务满足原子性。事务队列中的命令要么全部执行,要么全部放弃。
需要注意的是,如果在事务队列中的命令执行的时候,某些命令执行出错,那么也不会影响其他命令的执行。比如命令A,B,C,D是在一个事务中,假如B执行出错了,那么ACD三个命令依然会执行,并且执行结果也会生效。这一点与MySQL等关系型数据库不同,原因在于Redis事务不支持回滚,而不支持回滚的原因是Redis的开发者认为这会使redis复杂。

隔离型

Redis是单线程的,并且服务端保证在执行事务期间不会对事务进行中断,所以Redis的事务总是以串行方式运行的,所以,Redis的事务也是具有隔离性的。

一致性

数据库的一致性指的是数据库中数据的状态变化总是从一个一致性的状态变化到另外一个一致性的状态。即事务执行前是一致的,事务执行之后,状态也应该是一致的。
Redis事务也具备一致性,从以下三个方面进行保证:

入队错误

事务开启后,如果一个命令入队时出错(比如命令的参数个数不对或者命令不存在),那么收到客户端的EXEC命令之后,Redis将拒绝执行事务。
PS:入队错误,不会返回给客户端QUEUED,所以客户端可以知道命令出错,最后通

源码阅读 HashMap    2016-04-30 23:17:48    550    0    0

现象

如果你有仔细阅读过HashMap的源码,那么你一定注意过一个问题:HashMap中有两个私有方法。
private void writeObject(java.io.ObjectOutputStream s) throws IOException
private void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException
这两个方法有两个共同点:
1. 都是私有方法
2. 虽然是私有方法,但是在HashMap内部却找不到任何调用它们的地方

疑问

  1. 这两个方法是干嘛用的?
  2. 为什么要设置成私有的?、

解答

1. HashMap中的writeObject和readObject方法的作用是什么?

答:readObject和writeObject方法都是为了HashMap的序列化而创建的。
首先,HashMap实现了Serializable接口,这意味着该类可以被序列化,而JDK提供的对于Java对象序列化操作的类是ObjectOutputStream,反序列化的类是ObjectInputStream。我们来看下序列化使用的ObjectOutputStream,它提供了不同的方法用来序列化不同类型的对象,比如writeBoolean,wrietInt,writeLong等,对于自定义类型,提供了writeObject方法。
ObjectOutputStream的writeObject方法会调用下面的方法:

  1. private void writeSerialData(Object obj, ObjectStreamClass desc)
  2. throws IOException
  3. {
  4. ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();
  5. for (int i = 0; i < slots.length; i++) {
  6. ObjectStreamClass slotDesc = slot
spring    2016-04-29 12:29:25    1500    0    0

问题描述

项目中有一个接口ConfigService,该接口有一个实现类RedisDBConfigService,实现类中有个方法使用了Spring的事务注解@Transactional,代码大致如下:

  1. @Service
  2. public class RedisDBConfigService implements ConfigService {
  3. @Autowired
  4. private DataMapper mapper;
  5. //为了做单元测试,提供一个set方法
  6. public void setDataMapper(DataMapper dataMapper) {
  7. this.mapper = dataMapper;
  8. }
  9. //基于Spring事务控制
  10. @Transactional(rollbackFor = Exception.class)
  11. @Override
  12. public void updateConfig(Data data) throws Exception {
  13. doSomething();
  14. }
  15. }

Spring的事务配置如下:

  1. <!-- 注解方式配置事物 -->
  2. <tx:annotation-driven transaction-manager="transactionManager"/>

这种方式有一个隐含条件就是:Spring为需要事务控制的类创建代理的时候,默认使用JDKProxy来创建。

以上是前提条件。这里要说明一下,程序并没有任何问题,上面的设置也是正确的,可以正确无误运行。那么这样的设置出现了什么问题呢?

问题回放

问题出在单元测试上。如果仅仅测试一下updateConfig方法能否正确运行,是很简单的,也不会有问题。但是单元测试的意义不仅于此,有时候我们需要测试一些异常情况。
比如这个例子中,我需要测试一下DataMapper执行出错抛异常的时候程序的运行结果。为了让程序抛异常,我的思路是自己实现一个DataMapper,然后在方法中直接抛出异常,然后将该DataMapper赋值给RedisDBConfigServ