为什么阿里禁止通过Executors创建线程池

Executors是通过new一个ThreadPoolExecutor来创建的线程池。来看看ThreadPoolExecutor的构造方法:

1
2
3
4
5
6
7
8
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
阅读更多

对变量加锁后是否还需要使用volatile

大家都知道volatile保证了变量在线程间的可见性(主内存与CPU缓存(线程内存)间)。Lock与synchronized也可以保证可见性,还能保证原子性。
那么使用了Lock与synchronized之后,变量是否就不用加volatile了?

阅读更多

记一个Spring Data JPA自定义分页查询BUG

官方给出的自定义分页查询的示例是这样的:

1
2
3
4
5
6
public interface UserRepository extends JpaRepository<User, Long> {
@Query(value = "SELECT * FROM USERS WHERE LASTNAME = ?1",
countQuery = "SELECT count(*) FROM USERS WHERE LASTNAME = ?1",
nativeQuery = true)
Page<User> findByLastname(String lastname, Pageable pageable);
}
阅读更多

Stream的TerminalOp执行原理

Stream在执行intermediate(例如 map、filter)操作时,会形成referencePipeline 双向链表。

TermianlOp执行时遍历链表:

1
2
3
for ( AbstractPipeline p=AbstractPipeline.this; p.depth > 0; p=p.previousStage) {
sink = p.opWrapSink(p.previousStage.combinedFlags, sink);
}

执行StatelessOp 中Sink的OnWrapSink。
(通过Sink 中ChainedReference 翻转)

所以Stream中的元素是依次应用intermediate操作。并不是所有元素应用完第一个intermediate操作,在应用下一个。

PS:使用Stream时,首先会构建一个HEAD-源阶段(Stream()),然后经历StatelessOp-中间阶段(map、filter),最终通过TermianlOp(reduce等)

IDEA-Scratches的一个问题

新建一个scratch,编写如下代码:

1
2
List<String> list = Arrays.asList("11 22","22 11","32 44");
list.stream().map(item->item.split(" ")).flatMap(Arrays::stream).distinct().collect(Collectors.toList()).forEach(System.out::println);

其中Arrays::stream,编译错误,提示Cannot resolve method ‘stream’
在工程中编写则无此错误。

IDEA版本:2018.3.2 UE版
JDK:jdk1.8.0_121

MySQL 事务查询

查询事务
SELECT * FROM information_schema.INNODB_TRX;

查询正在锁的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;

查询等待锁的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;

查询进程
show PROCESSLIST;

查询是否锁表
show OPEN TABLES where In_use > 0;

Maven Settings 中的一些容易混淆的概念

首先是repositories,其中定义了一些远程仓库(私服)。本来是可以直接定义在POM.xml ,但是由于一个公司通常多个项目都是使用的同一个远程仓库(私服)。为了每个项目不重复定义。所以可以统一配置在settings.xml。由于settings下不能直接定义repositories所以采用了profiles。同时也可以使用profiles做不同环境下的配置切换。

容易混淆的是mirrors,配置多个mirror,并不是每一个都会生效,始终只有第一个有用。另外mirrors 跟profiles没有什么直接关系,有关系的是repositorymirrorOf 中配置的是repository id(支持表达式)。一般我们mirror的都是central这类官方,因为mirror的主要作用就是解决不同网络环境下,这种官方的或者第三方的仓库速度问题。如果你有私服,然后直接mirrorOf * 到了阿里云的镜像库,那么你私服的Jar可能就访问不到了。

maven找Jar的路径大概是,本地仓库>各个远程库,如果配置了镜像,则走镜像库。

server配置的是maven私服账号密码信息,用于分发jar到私服时认证,通常在pom文件中会定义distributionManagement,其中repository id 必须和server的id一致。
分发指的是deployinstall只会在本地库中存在。

MySQL可重复读和幻读

可重复读描述的是一个事务在处理数据时,多次查询此数据得到的结果是一样的。MySQL的InnoDB存储引擎通过多版本并发控制(Multi_Version Concurrency Control, MVCC)机制来解决该问题。
幻读描述的是MVCC不能阻止插入新的数据,导致多次查询时数据记录不一致。

CAP个人浅显的理解

分布式系统为了保证数据不丢失,于是我们将数据做了多个副本放在了不同的服务器上【Partition tolerance(分区耐受性): 可靠性)】,并且保持更新多个副本,但是在更新副本的时候,可能由于网络等诸多原因导致其中一个或多个副本无法更新,此时就面临了一个选择:更新剩下的副本?or 都不更新了?
选择更新剩下的副本,则是选择了【Availability(可用性): 好的响应性能】,此类型系统保证了AP。
选择都不更新了,则是选择了【Consistency(一致性): 数据一致更新】,此类型系统保证了CP。

以上为个人片面且浅显的理解。