java多线程学习(四)—— ConcurrentHashMap和CountDownLatch的使用

ConcurrentHashMap

1、在jdk中,我们常用的map集合是 HashTableHashMap 这两个,其中HashTable是线程安全的,即里面的每一个方法都是线程同步的方法,使用了synchronized关键字修饰,而HashMap是线程不安全的。
2、虽然HashTable是线程安全的,但是效率很低,所以在jdk1.5之后,在并发包中就增加了一个线程安全,效率也高的map集合,叫 ConcurrentHashMap
3、ConcurrentHashMap 是接口ConcurrentMap的实现类,它还有一个实现类,是ConcurrentskipListMap (支持并发排序功能。弥补ConcurrentHas hMa p)
4、ConcurrentHashMap内部使用段(Segment)来表示这些不同的部分,每个段其实就是一个
小的HashTable,它们有自己的锁。只要多个修改操作发生在不同的段上,它们就可以并
发进行。把一个整体分成了16个段(Segment.也就是最高支持16个线程的并发修改操作。
这也是在重线程场景时减小锁的粒度从而降低锁竞争的一种方案。并且代码中大多共享变
量使用volatile关键字声明,目的是第一时间获取修改的内容,性能非常好。(这个也就是分段锁)

CountDownLatch

CountDownLatch类位于java.util.concurrent包下,利用它可以实现类似计数器的功能。
比如有一个任务A,它要等待其他4个任务执行完毕之后才能执行,此时就可以利用CountDownLatch来实现这种功能了。

public class Test002 {

	public static void main(String[] args) throws InterruptedException {
		System.out.println("等待子线程执行完毕...");
		CountDownLatch countDownLatch = new CountDownLatch(2);
		new Thread(new Runnable() {

			@Override
			public void run() {
				System.out.println("子线程," + Thread.currentThread().getName() + "开始执行...");
				countDownLatch.countDown();// 每次减去1
				System.out.println("子线程," + Thread.currentThread().getName() + "结束执行...");
			}
		}).start();
		new Thread(new Runnable() {

			@Override
			public void run() {
				System.out.println("子线程," + Thread.currentThread().getName() + "开始执行...");
				//countDownLatch技术器减一
				countDownLatch.countDown();
				System.out.println("子线程," + Thread.currentThread().getName() + "结束执行...");
			}
		}).start();

		// 调用当前方法主线程阻塞  直到countDown结果为0, 阻塞变为运行状态
		countDownLatch.await();
		System.out.println("两个子线程执行完毕....");
		System.out.println("继续主线程执行..");
	}
}

分析:上面的代码中,定义了一个全局的countDownLatch技术器,让主线程和两个子线程都可以访问这个countDownLatch技术器,每一个子线程运行完,countDownLatch技术器就减一,而主线程调用了countDownLatch.await()方法,一直处于阻塞状态,知道两个线程都运行完,countDownLatch技术器变成0,主线程才继续执行
注意:上面的代码中,如果countDownLatch技术器初始值为 1 ,而有两个线程,此时也不会报错,只是在一个线程执行完成后,countDownLatch变成0,主线程就会和另一个子线程竞争cpu资源

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章