0%

零、本文由来

感觉从业这么久以来,读取文件路径相关问题一直是一个痛
用的很少,之前也解决过相关的问题
但是得用这种路径

1
src/test/resources/test/test.txt

上面这种路径如果在代码中的话,src/test/resources是不会存在的,会出现问题
本次学到了一个新的方法,Class.getResourceAsStream();
需要的路径在资源文件夹下面即可,填写路径:/test/test.txt
打包最终的路径会在:WEB-INF/classes/test/test.txt

ps:因maven打包配置不同,最终resources资源文件夹下的路径是不同的,注意src的坑即可

一、文件结构

1
2
3
4
5
6
7
│   └── test
│   ├── java
│   │   └── mq
│   │   └── Test.java
│   └── resources
│   ├── test
│   │   └── test.txt

二、读取代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@RunWith(value = SpringJUnit4ClassRunner.class)
@ContextConfiguration({"/spring-config.xml"})
public class Test {
@Test
public void test() throws IOException {
InputStream inputStream = Test.class.getResourceAsStream("/test/test.txt");
byte[] buffer = new byte[1024];
int len;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
while ((len = inputStream.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
bos.close();
String res = bos.toString();
System.out.println(res);
}
}

一、volatile是什么

volatile是Java提供的一种轻量级的同步机制
保证变量的修改其它线程立马可见,解决部分并发问题

二、volatile局限性

无法解决复合操作,例如 i++ i–这种操作
原因:i++操作分三步

  1. 读取i=1;
  2. i=i+1=2;
  3. i=2写入主存
    有可能在3写入之前,其它线程已经对i进行了修改,比如改为100了,结果覆盖写入了2

三、volatile原理

volatile底层依靠指令重排序来实现内存可见性的
具体的规则如下

  1. 当第二个操作是voaltile写时,无论第一个操作是什么,都不能进行重排序
  2. 当第一个操作是volatile读时,不管第二个操作是什么,都不能进行重排序
  3. 当第一个操作是volatile写时,第二个操作是volatile读时,不能进行重排序
Read more »

一、为什么用缓存

1.1 空间换时间:

缓存是针对读多写少的场景典型的以空间换时间的操作
空间:内存
时间:读内存速度快(相对于读磁盘)

1.2 局部性原理:

这个世界很多事情都符合 2/8 原则
把热点数据缓存起来就大大提高系统效率

二、缓存组件介绍

2.1 Ehcache

  1. 快速,针对大型高并发系统场景,Ehcache 的多线程机制有相应的优化改善;
  2. 简单,很小的 jar 包,简单配置就可直接使用,单机场景下无需过多的其他服务依赖;
  3. 支持多种的缓存策略,灵活;
  4. 缓存数据有两级:内存和磁盘,与一般的本地内存缓存相比,有了磁盘的存储空间,将可以支持更大量的数据缓存需求;
  5. 具有缓存和缓存管理器的侦听接口,能更简单方便的进行缓存实例的监控管理;
  6. 支持多缓存管理器实例,以及一个实例的多个缓存区域;

2.2 Guava

  1. 自动将 entry 节点加载进缓存结构中;
  2. 当缓存的数据超过设置的最大值时,使用 LRU 算法移除;
  3. 具备根据 entry 节点上次被访问或者写入时间计算它的过期机制;
  4. 缓存的 key 被封装在 WeakReference 引用内;
  5. 缓存的 Value 被封装在W eakReference 或 SoftReference 引用内;
  6. 统计缓存使用过程中命中率、异常率、未命中率等统计数据;
Read more »

一、理论知识

常见参数:

  1. -Xms 堆初始化 例如:-Xms256m
  2. -Xmx 堆最大值 例如:-Xmx512m
  3. -Xmn 堆新生代 例如:-Xmn100m
  4. -XX:NewRatio 新生代与老年代的比例
  5. -XX:SurvivorRatio 新生代区域比例,默认8,代表Eden:From Survivor:To Survivor = 8:1:1

垃圾回收器:

  1. Serial/Serial Old 新生代/老年代,古老,单线程,暂停所有用户线程,复制算法/标记整理算法
  2. ParNew 1的多线程版本
  3. Parallel Scavenge 新生代,多线程,不需要暂停用户线程,复制算法
  4. Parallel Old 老年代,多线程,不需要暂停用户线程,标记整理算法
  5. CMS(Current Mark Sweep,详情)老年代,与ParNew配合使用,牺牲吞吐量获得最短停顿,标记整理算法
  6. G1 并行与并发收集器,可预测的停顿时间

二、实践案例

  1. Full GC 之前进行 Minor GC 避免扫描过多的对象, 配置:CMSScavengeBeforeRemark
  2. Xms和Xmx设置为相同,这样可以减少内存自动扩容和收缩带来的性能损失
  3. JVM调优是最后的稻草,进行JVM调优之前应该先优化架构和代码
  4. 调优是一个复杂的过程,根据具体的场景结合对垃圾回收器的深入理解进行调优,才可能事半功倍。

各个区大小比例建议

1
2
3
4
5
# 活跃空间大小:Full GC后堆中老年代占用空间的大小
空间 倍数
总大小 3-4倍活跃空间大小
新生代 1-1.5倍活跃空间大小
老年代 2-3倍活跃空间大小
Read more »

一、简单介绍

除了runtimeException以外的异常,都属于checkedException。

CheckedException(受检异常):编译器会检查这类异常,需要强制捕获,否则无法编译通过。
UnCheckedException(非受检异常):编译器不会检查这类异常,可以不用捕获,可以编译通过。

二、常见异常

受检:IOException、SQLException、NumberFormatException、IllegalArgumentException
非受检:OutOfMemoryError、StackOverflowError、NullPointerException、IndexOutOfBoundsException

点击查看所有jdk8 api文档
进去可以看到java.lang.RuntimeException下有很多子类异常

暂时写这些,日后再完善

一、什么是Curator

Apache Curator is a Java/JVM client library for Apache ZooKeeper, a distributed coordination service.
It includes a highlevel API framework and utilities to make using Apache ZooKeeper much easier and more reliable.
It also includes recipes for common use cases and extensions such as service discovery and a Java 8 asynchronous DSL.

特别说明:Guava is to Java What Curator is to ZooKeeper

二、常见用法

后期补上自己的一些demo,其实官方文档已经介绍很全了
http://curator.apache.org/getting-started.html

三、其它说明

了解这个客户端是在《从Paxos到Zookeeper:分布式一致性原理与实战》这本书里面看到的(书单)
Curator号称是世界上最好用的zk客户端,相比zkClinet来说拥有更好的封装
让我想起Redisson和Jedis的模样

昨天一个做移动端的前同事截图问我那些代码什么意思,用的就是Curator封装的分布式锁

相比于Redis分布式存在超时问题,zookeeper分布式锁利用临时节点可以避免

目前dubbo master上使用的是Curator 4.0.1

一、Guice简介

Google公司的Bob lee开发的轻量级IoC容器,其特点是:

  1. 速度快,号称是spring的100倍速度
  2. 无配置文件,实用JDK5.0的annotation描述组件依赖,简单,而且有编译器检查和重构支持
  3. 简单,代码量很少

二、简单样例

  1. 详细代码:https://github.com/hisenyuan/IDEAPractice/tree/master/src/main/java/com/hisen/jars/guice
  2. 依赖
1
2
3
4
5
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>4.2.2</version>
</dependency>
  1. 测试类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class HelloApp extends BaseServer {
@Inject
private HelloServiceImpl hello;

@Test
public void testSayHello() {
// 方式一
Injector injector = Guice.createInjector();
HelloService helloService = injector.getInstance(HelloService.class);
helloService.sayHello("hisen");

// 方式二 其实是在BaseServer中做了方式1的事情 【类似Spring的方式】
hello.sayHello("1");
}
}

三、解决问题

1
java.lang.NoSuchMethodError: com.google.common.base.Preconditions.checkArgument(ZLjava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)V

github有人遇到同样的问题:https://github.com/SeleniumHQ/selenium/issues/3880

把本地的guava版本由19.0改为21.0成功解决问题

一、名词解释

1.1 同步与异步

同步与异步主要是针对CPU来说的

  1. 同步:CPU必须等着结果返回,这期间不能干别的;
  2. 异步:CPU不必等着结果返回,这期间可以干别的;

1.2 阻塞与非阻塞

阻塞与非阻塞主要是针对I/O来说的

  1. 阻塞:I/O线程会挂起,需等待结果;
  2. 非阻塞:I/O线程不必挂起,不等待结果;

1.3 伪异步I/O

本质上还是同步阻塞I/O
不过是在服务器把socket链接封装成Task提交给线程池处理
因为有队列,所以可以突破C:S=1:1的比例

1.4 I/O多路复用

通过把多个I/O的阻塞复用到一个阻塞上,从而使得系统在单线程情况下可以处理多个客户端的请求。
类似于linux的epoll、select

1.5 多路复用器

Selector,核心是通过Selector来轮询注册在其上的Channel
当发现有Channel就绪就返回Channel的选择键集合,进行I/O操作;

二、不同I/O模型对比表格

Read more »

这是之前的一个帖子:oracle - mysql - 数据库事务隔离级别介绍
写的不全面, 按现在的理解,重新写一个;

一、名词解释

脏读:在一个查询事务过程中,读到了其它事务没有提交的数据;
不可重复读:一个事务查询过程中,多次查询得到了不一致的结果,原因是:有别的更新事务提交了;
幻读:一个事务查询过程中,多次查询得到了不一致的结果,原因是:有别的删除事务/插入事务提交了;

二、数据库隔离级别

| name | 名称 | 脏读 | 不可重复读 | 幻读 | 加锁读 |
|:—–|:—–|:—–|:—–|:—–|:—–| :—–|
| Read uncommitted | 读未提交 | Yes | Yes | Yes | No |
| Read committed | 读已提交 | No | Yes | Yes | No |
| Repeatable read | 可重复读 | No | No | Yes | No |
| Serializable | 序列化 | No | No | No | Yes |

默认的隔离级别为:RR,原因:5.1之后版本,如果Binlogog开启语句级别,必须为RR,RC可能会导致Binlog数据错误(详情);

三、控制方式

读未提交:每次都是读数据最新的版本(包括事务未提交的数据);
读已提交:MVCC控制;
可重复读:MVCC控制;
序列化:在读取的每一行上加锁,只能按顺序进行读写;

四、InnoDB MVCC(多版本并发控制)原理

Read more »

一、命令组合

1
2
3
4
$ more sort.log | awk '{print $1}' | sort | uniq -c | sort -k1nr | head -3
4 5
3 1
2 2

二、命令详解

more:一次读取少量的数据,避免一次性载入大文件,比cat好些
awk ‘{print $1}’:以awk默认的分隔符,并且打印第一列
sort:把上一步的结果按ASCII排序
uniq -c:如果重复那么计数,uniq命令可以组合很多其它参数
sort -k1nr:根据第一列的数据进行排序,n是按数值大小排序,r是倒序排序
head -3:显示前面三行数据

三、原始数据

Read more »