ThreadPoolExecutor原理

并发包描述

java.util.concurrent

Utility classes commonly useful in concurrent programming.

https://docs.oracle.com/javase/7/docs/api/

java.util.concurrent.atomic

A small toolkit of classes that support lock-free thread-safe programming on single variables.

java.util.concurrent.locks

Interfaces and classes providing a framework for locking and waiting for conditions that is distinct from built-in synchronization and monitors.

Read More ...

IDEA心得不定期更新

记录一些 IDEA 使用中的各种小问题

debug step in 失效

红框内的打钩去掉就OK了,看源码的时候勾上了真是蛋疼

另外,如果 debug 的代码是一个非 Main 的线程,但是如果 debug 到一半 Main 方法结束,即 JVM 运行结束,会导致 step in 按下以后直接结束掉。这个时候像个办法让 Main 方法永远不结束就行了。

Read More ...

AbstractQueuedSynchronizer排他锁分析

ThreadPoolExecutor.Worker 继承自 AbstractQueuedSynchronizer,并实现了一些锁相关的方法:

1
2
3
4
public void lock()        { acquire(1); }
public boolean tryLock() { return tryAcquire(1); }
public void unlock() { release(1); }
public boolean isLocked() { return isHeldExclusively(); }

锁的实现:

1
2
3
4
5
6
public final void acquire(int arg) {
// 利用CAS尝试去更新state,如果失败就要进入等待队列
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}

Read More ...

Spring IOC循环引用源码分析

Spring bean 有两种注入方式,构造器注入和 set 注入。后者经过测试循环引用是不会报异常的,前者会报异常。

set 的方式

set 的方式默认是支持循环引用的,如果想设置成不支持,可以将 BeanFactory 实现类的 allowCircularReferences 设置成 falses。ApplicationContext 和 BeanFactory 基础的实现类都有这个参数可以设置。

spring 初始化 bean 的时候,是先构造一个空的对象,然后再根据需要去初始化属性指向的 bean。比如 B1 -> B2 为 B1 后属性引用 B2,同时 B2 -> B1。当去初始化 B2 的时候,在设置自己指向 B1 的属性时,是直接用 B1 还未完全构造完成的对象。

比如 B2 在需要去设置对 B1 的引用时,会调用 BeanFactory 的 getBean 方法。这个 getBean 方法的逻辑在最前端会去查一个缓存,这个缓存里放了先前已经开始初始化,但是还没有把属性设置完全的 bean 引用缓存。如果缓存非空,就直接用这个引用返回。如果缓存为空,就去调一个 ObjectFactory 对象的 getObject 方法作为 bean 引用返回。这个 ObjectFactory 是先前 B1 初始化时,被 new 出来以后,加进一个 ObjectFactory 容器的:

1
2
3
4
5
6
// AbstractAutowireCapableBeanFactory.doCreateBean
addSingletonFactory(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});

Read More ...

Java类加载探究

class loading 理解

编译型语言的连接和Java的连接

C/C++等纯编译语言从源码到最终执行一般要经历:编译、连接和运行三个阶段,连接是在编译期间完成,而java在编译期间仅仅是将源码编译为Java虚拟机可以识别的字节码Class类文件,Java虚拟机对中Class类文件的加载、连接都在运行时执行

http://www.cnblogs.com/hnlshzx/p/3533264.html

编译型语言有连接,Java 也有连接,那么所谓的连接到底是干什么的。C 的连接:

把外部函数的代码(通常是后缀名为.lib和.a的文件),添加到可执行文件中。这就叫做连接(linking)。这种通过拷贝,将外部函数库添加到可执行文件的方式,叫做静态连接(static linking),后文会提到还有动态连接

http://www.ruanyifeng.com/blog/2014/11/compiler.html

看起来就是所谓连接,连接的是将有相互调用关系的代码(函数)对接到一起,让他们组织成一个可执行的整体(他们有调用关系,本来就该在一起)。那么 Java 的连接有是啥(Linking)?

Read More ...

MySQL一例间隙锁分析

研究间隙锁的时候碰到一个问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
CREATE TABLE `t2` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`a` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_a` (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

mysql> select * from t2;
+----+------+
| id | a |
+----+------+
| 1 | 2 |
| 3 | 4 |
| 6 | 5 |
| 8 | 5 |
| 10 | 5 |
| 13 | 11 |
+----+------+

Read More ...