CyclicBarrier详解

在上一篇的文章中有提到过 CountDownLatch ,其实 CyclicBarrier 也有异曲同工之妙,不过 CyclicBarrier 是等到所有的线程都到达一个点以后,然后再一起执行

有点像小时候一起去春游,必须等到所有的同学都到了学校,才能一起去坐车,不然就会一直等待。

构造函数

CyclicBarrier 的构造函数有两个,分别如下:

1
2
3
public CyclicBarrier(int parties) {
this(parties, null);
}
阅读更多

CountDownLatch详解

CountDownLatch

CountDownLatch 只有一个构造函数:CountDownLatch(int count)

其中 count 表示该信号量的数量,其中具体的实现类是 Sync,而 Sycn 又是继承自 AQS,实现了几个 AQS 的方法

在生产环境中可以用于分治思想,讲一些复杂的处理分成一些子任务,等所有处理任务处理完毕以后,主线程才会执行

还可以用于一些任务的流程检查,例如只有所有的检查都完毕以后,主线程才可以获取数据然后执行

阅读更多

浅谈 synchronized 和 volatile

一、锁

从细节上来说,锁分为 乐观锁、悲观锁

乐观锁适用于读多写少的场景,一般是通过 CAS 进行操作,因为不用加锁,所以性能上比悲观锁优秀太多

悲观锁适用于写多读少的场景,性能开销比较大。

1:乐观锁

阅读更多

WeakHashMap的实现原理

简介

什么是WeakHashMap

WeakHashMap实现了 Map 接口,属于 Java 集合中的一员,其用法几乎和 HashMap 一致,但是由于它的 Entry 还继承了 WeakHashMap ,因此导致它的这个 Entry 在触发 FullGc 的时候是有可能可以被回收的。

以下测试,JVM参数统一为:-Xmx64M -Xms64M -XX:+PrintGCDetails

首先上一段代码:

阅读更多

重温Java中String

本文的内容都是基于 JDK1.8 来写的,主要是复习下 String 类的设计。

简介

String 是一个用于存储字符串的类,其内部是通过 char 数组来实现,在 Java 中,1byte = 8bit,1char = 2byte, 所以在 Java 中,String 的code point是16位。
String 类是由 final 关键字来修饰的,因此表明该类不可以被继承,同时 String 又实现了 Serializable、Comparable、CharSequence接口,表明 String 可以被序列化,以及使用cpmpareTo来比较两个字符串的值。

字符集编码

内码

阅读更多

JDK1.8下ConcurrentHashMap的一些理解(一)

在JDK1.8里面,ConcurrentHashMap在put方法里面已经将分段锁移除了,转而是CAS锁和synchronized

ConcurrentHashMap是Java里面同时兼顾性能和线程安全的一个键值对集合,同属于键值对的集合还有HashTable以及HashMap
HashTable是一个线程安全的类,因为它的所有public方法都被synchronized修饰,这样就导致了一个问题,就是效率太低。

虽然HashMapJDK1.8的并发场景下触发扩容时不会出现成环了,但是会出现数据丢失的情况。
所以如果需要在多线程的情况下(多读少写))使用Map集合的话,ConcurrentHashMap是一个不错的选择。

ConcurrentHashMap在JDK1.8的时候将put()方法中的分段锁Segment移除,转而采用一种CAS锁和synchronized来实现插入方法的线程安全。
如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/** Implementation for put and putIfAbsent */
final V putVal(K key, V value, boolean onlyIfAbsent) {
//省略相关代码
for (Node<K,V>[] tab = table;;) {
Node<K,V> f; int n, i, fh;
if (tab == null || (n = tab.length) == 0)
tab = initTable();
else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
if (casTabAt(tab, i, null,
new Node<K,V>(hash, key, value, null)))
break; // no lock when adding to empty bin
}
else if ((fh = f.hash) == MOVED)
tab = helpTransfer(tab, f);
else {
V oldVal = null;
synchronized (f) {
//省略相关代码
}
if (binCount != 0) {
if (binCount >= TREEIFY_THRESHOLD)
treeifyBin(tab, i);
if (oldVal != null)
return oldVal;
break;
}
}
}
addCount(1L, binCount);
return null;
}
阅读更多

Error是真的不可以被捕获的吗?

在刚接触Java的时候经常听到的一句话便是在 Java 中,Exception 是可以捕获的,Error 是不可以捕获的。但是在随着学习的深入,会发现有些观点需要重新认识下了。
Throwable 这个类是自 JDK1.0 开始就存在于 Java 的语言之中。

Throwable

首先引用一段 Oracle 官方文档上对 Throwable 的介绍Java8 Thrwoable的介绍

The Throwable class is the superclass of all errors and exceptions in the Java language. Only objects that are instances of this class (or one of its subclasses) are thrown by the Java Virtual Machine or can be thrown by the Java throw statement. Similarly, only this class or one of its subclasses can be the argument type in a catch clause. For the purposes of compile-time checking of exceptions, Throwable and any subclass of Throwable that is not also a subclass of either RuntimeException or Error are regarded as checked exceptions.
Instances of two subclasses, Error and Exception, are conventionally used to indicate that exceptional situations have occurred. Typically, these instances are freshly created in the context of the exceptional situation so as to include relevant information (such as stack trace data).
太长,省略大部分了……

简单翻译下就是,Throwable 是 Error 和 Exception 的父类,并且只能是 Error 和 Exception 的实例才可以通过 throw 语句或者 Java虚拟机 抛出异常。Exception 或者 Error 是在出错的情况下新创建的,从而将出错的信息和数据包含进去。
另外在这个文档中还提到了一点就是当低层方法向高层方法抛出异常的时候,如果抛出的异常是受检查的异常,则

阅读更多

TreeSet和TreeMap的一点总结

首先简单介绍下TreeSet和TreeMap的两种排序:

  • 自然排序
  • 通过comparator排序
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    private static void compareWithCpmparator(){
    TreeSet<String> treeSet =new TreeSet<>();
    List<String> list =new ArrayList<>();
    list.add("a");
    list.add("d");
    list.add("b");
    treeSet.addAll(list);
    Iterator<String> iterator =treeSet.iterator();
    while (iterator.hasNext()){
    System.out.println(iterator.next());
    }
    Comparator<String> comparator1 = (Comparator<String>) treeSet.comparator();
    if (comparator1 == null){
    System.out.println("comparator1是空");
    }else {
    System.out.println("comparator1不是空");
    }
    }

    public static void main(String[] args) {
    compareWithCpmparator();
    }
    运行之后的结果如下:
    1
    2
    3
    4
    a
    b
    d
    comparator1是空
    这段代码里面获取的comparator是空的,Debug一遍,发现这个方法其实调用的是NavigableMap里面的comparator
    1
    2
    3
    public Comparator<? super E> comparator() {
    return m.comparator();
    }
    查看官网上对其的介绍:
    1
    2
    3
    4
    Comparator<? super K> comparator()
    Returns the comparator used to order the keys in this map, or null if this map uses the natural ordering of its keys.
    Returns:
    the comparator used to order the keys in this map, or null if this map uses the natural ordering of its keys
    在调用这个方法的时候若是自然排序,那么会返回一个null。若是通过comparator进行排序的话当前集合采用的comparator
    查看官网对reeSet的无参构造器的解释:

    /**

    • Constructs a new, empty tree set, sorted according to the
    • natural ordering of its elements. All elements inserted into
    • the set must implement the {@link Comparable} interface.
    • Furthermore, all such elements must be mutually
    • comparable: {@code e1.compareTo(e2)} must not throw a
    • {@code ClassCastException} for any elements {@code e1} and
    • {@code e2} in the set. If the user attempts to add an element
    • to the set that violates this constraint (for example, the user
    • attempts to add a string element to a set whose elements are
    • integers), the {@code add} call will throw a
    • {@code ClassCastException}.

在使用TreeSet的时候,插入的元素需要实现Comparable这个接口,而刚刚的元素是String,查看String的代码发现:

1
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {

确实实现了,再测试一个没有实现的元素:

阅读更多