Java8的深入与实战
分布式事务框架Seata

分布式事务框架Seata

分布式基础

CAP 定理

CAP 定理指的是在一个分布式系统中, Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可兼得。在分布式系统中,分区容错性是必须需要实现的。所以只能在一致性和可用性之间进行权衡(AP 或者 CP)。

Read more
关于null的思考

关于null的思考

写代码的时候有个地方需要把 Integer 类型强转为 String

Integer firstEventType = eventTask.getEventType1();
String firstEventTypeName = eventTypeService.queryDescByCode(String.valueOf(firstEventType));

当我点开 String#valueof 这个静态方式时

public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}

当我们没有获取到 firstEventType 这个值时,为 null,此时它返回给我们的是字符串 “null” ,有时候就不符合我们的业务场景,最好是提前做空值判断。

Read more
JVM 面试

JVM 面试

JVM 垃圾回收的时候如何确定垃圾?知道什么是 GC Roots ?

  • 什么是垃圾
    • 简单来说就是内存中已经不在被使用到的空间就是垃圾
  • 要进行垃圾回收,如何判断一个对象是否可以被回收?
    • 引用计数法
    • 枚举根节点做可达性分析
Read more
Java 并发编程

Java 并发编程

请谈谈你对 volatile 的理解

volatile 是 Java 虚拟机提供的轻量级的同步机制

  • 保证可见性
  • 禁止指令排序
  • 不保证原子性
Read more
生产者消费者

生产者消费者

维基百科解释:

In computing, the producer–consumer problem[1][2] (also known as the bounded-buffer problem) is a classic example of a multi-process synchronization problem. The problem describes two processes, the producer and the consumer, who share a common, fixed-size buffer used as a queue. The producer’s job is to generate data, put it into the buffer, and start again. At the same time, the consumer is consuming the data (i.e., removing it from the buffer), one piece at a time. The problem is to make sure that the producer won’t try to add data into the buffer if it’s full and that the consumer won’t try to remove data from an empty buffer.

import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
* @Author: cuzz
* @Date: 2019/4/6 13:03
* @Description: 生产者消费者
*/
public class ProducerConsumerDemo {
public static void main(String[] args) {
Container container = new Container();
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.execute(() -> container.produce());
executor.execute(() -> container.consume());
executor.shutdown();
}
}

class Container {
private List<Integer> list = new LinkedList<>();
private final int MAX_SIZE = 5;

private Random random = new Random();

public void produce() {
while (true) {
synchronized (this) {
try {
while (list.size() >= MAX_SIZE) {
wait();
}
int i = random.nextInt();
System.out.println("produce..." + i);
list.add(i);
notify();
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

public void consume() {
while (true) {
try {
synchronized (this) {
while (list.isEmpty()) {
wait();
}
int i = list.remove(0);
System.out.println("consume..." + i);
notify();
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
LRUCache

LRUCache

LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高” 。

代码:

/**
* @Author: cuzz
* @Date: 2019/3/16 15:35
* @Description: LRU cache
*/
public class LRUCache {

private Map<Integer, DLinkedList> cache = new HashMap<>();
private int count;
private int capacity;
private DLinkedList head, tail;

public LRUCache(int capacity) {
this.count = 0;
this.capacity = capacity;

this.head = new DLinkedList();
this.tail = new DLinkedList();

head.next = tail;
tail.pre = head;
}

public int get(int key) {
DLinkedList node = cache.get(key);
if (node == null) {
return -1;
}
removeNode(node);
addHead(node);
return node.value;
}

public void put(int key, int value) {
DLinkedList node = cache.get(key);
if (node == null) {
node = new DLinkedList(key, value);
addHead(node);
cache.put(key, node);
count++;
if (count > capacity) {
DLinkedList preTail = tail.pre;
removeNode(preTail);
cache.remove(preTail.key);
count--;
}
} else {
node.value = value;
removeNode(node);
addHead(node);
}

}

// 移除给定的结点
private void removeNode(DLinkedList node) {
DLinkedList pre = node.pre;
DLinkedList next = node.next;
pre.next = next;
next.pre = pre;
}

// 把结点添加头节点
private void addHead(DLinkedList node) {
DLinkedList next = head.next;
head.next = node;
node.next = next;
next.pre = node;
node.pre = head;
}

public static void main(String[] args) {
LRUCache cache = new LRUCache(2);
cache.put(1, 1);
cache.put(2, 2);
System.out.println(cache.get(1)); // 返回 1
cache.put(3, 3); // 使 2 作废
System.out.println(cache.get(2)); // 返回 -1
cache.put(4, 4); // 使 1 作废
System.out.println(cache.get(1)); // 返回 -1 未找到
System.out.println(cache.get(3)); // 返回 3
System.out.println(cache.get(4)); // 返回 4
}

}

class DLinkedList {
int key;
int value;
DLinkedList pre;
DLinkedList next;

public DLinkedList() {};

public DLinkedList(int key, int value) {
this.key = key;
this.value = value;
}
}
深入理解Java虚拟机(四)
Java中是如何实现线程通信

Java中是如何实现线程通信

正常情况下,每个子线程完成各自的任务就可以结束了。不过有的时候,我们希望多个线程协同工作来完成某个任务,这时就涉及到了线程间通信了。

本文涉及到的知识点:thread.join(), object.wait(), object.notify(), CountdownLatch, CyclicBarrier, FutureTask, Callable 等。

Read more

Java 中的锁

Java中的锁分类

在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类。介绍的内容如下:

Read more