java并发工具类

Hashtable

出现的原因:
      在集合类中HashMap是比较常用的集合对象,但是HashMap是线程不安全的(多线程环境下可能会存在问题),为了保证数据的安全性,可以使用Hashtable,但是Hashtable的效率底下,因为Hashtable底层代码是同步方法,当锁的时候是锁一整张table

示例代码

public class HashMapAndTable {

    public static void main(String[] args) throws InterruptedException {

        Hashtable<String,String> hashtable = new Hashtable<>();

        Thread thread1 = new Thread(() -> {

            for (int i = 0; i < 25; i++) {

                hashtable.put(i + "",i + "");
            }
        });

        Thread thread2 = new Thread(() -> {

            for (int i = 0; i < 51; i++) {

                hashtable.put(i + "",i + "");
            }
        });

        thread1.start();
        thread2.start();


        Thread.sleep(1000);

        for (int i = 0; i < 51; i++) {

            System.out.println(hashtable.get(i + ""));
        }
    }
}

ConcurrentHashMap

出现原因:
      在集合类中HashMap是比较常用的集合对象,但是HashMap是线程不安全的(多线程环境下可能会存在问题)。为了保证数据的安全性我们可以使用Hashtable,但是Hashtable的效率低下。基于以上两个原因我们可以使用JDK1.5以后所提供的ConcurrentHashMap。

体系结构
java并发工具类
代码示例

public class CurrentHashMap_ {

    public static void main(String[] args) throws InterruptedException {

        ConcurrentHashMap<String,String> concurrentHashMap = new ConcurrentHashMap<>();

        Thread thread_01 = new Thread(() -> {

            for (int i = 0; i < 25; i++) {

                concurrentHashMap.put(i + "",i + "");
            }
        });

        Thread thread_02 = new Thread(() -> {

            for (int i = 0; i < 51; i++) {

                concurrentHashMap.put(i + "",i + "");
            }
        });

        thread_01.start();
        thread_02.start();

        Thread.sleep(1000);

        for (int i = 0; i < 51; i++) {

            System.out.println(concurrentHashMap.get(i + ""));
        }
    }
}

总结:
1、HashMap是线程不安全的。多线程环境下会有数据安全问题

2、Hashtable是线程安全的,但是会将整张表锁起来,效率低下

3、ConcurrentHashMap也是线程安全的,效率较高。在 JDK7 和 JDK8中,底层原理不一样

ConcurrentHashMap 1,7原理
java并发工具类
1、默认创建一个长度16,步长为0.75的大数组(这个大数组一旦创建无法扩容)
2、还会创建一个长度为2的小数组,把地址值赋值给0索引处,其他索引位置的元素都是null

ConcurrentHashMap 1,8原理
java并发工具类
总结:
1、如果使用空参构造创建ConcurrentHashMap对象,则什么事都不做,在第一次添加元素的时候创建哈希表
2、计算当前元素应存入的索引
3、如果该索引位置为null,则利用CAS算法,将本节点添加到数组中
4、如果该索引位置不为null,则利用volatile关键字获得当前位置最新的节点地址,挂在他下面,变成一个链表
5、当链表的长度大于等于8时,自动转换成红黑树6,以链表或者红黑树节点为锁对象,配合悲观锁保证多线程操作集合时数据的安全性(只锁当前)

CountDownLatch

使用场景:让某一条线程等待其他线程执行完毕之后再执行

方法 解释
public CountDownLatch(int count) 参数传递线程数,表示等待线程数量
public void await() 让线程等待
public void countDown() 当前线程执行完毕

示例代码

public class CountDownLatch__ {
    public static void main(String[] args) {

        CountDownLatch count = new CountDownLatch(3);

        Thread thread = new Thread(() -> {

            for (int i = 0; i < 10; i++) {


                count.countDown();
                count.countDown();
                count.countDown();

                try {
                    count.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println("hello");
            }
        });

        thread.start();

    }
}

Semaphore

使用场景:可以控制访问特定资源的线程数量
public class Semaphore__ {
    public static void main(String[] args) {

		//可以控制访问特定资源的线程数量
        Semaphore semaphore = new Semaphore(2);

        Thread thread = new Thread(() -> {

            try {
                semaphore.acquire();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            for (int i = 0; i < 100; i++) {

                System.out.println("hello");
            }

            semaphore.release();
        });

        thread.start();
    }
}
上一篇:以HashMap和HashTable的区别


下一篇:数据结构与算法——哈希表(散列)