Java架构学习(四)Vector与ArrayList区别HashTable与HashMap源码分析ConcurrentHashMap(分段)CountDownLatch(类似计数的)Cycl

1、同步容器类


1、Vector

List实现类中包含Vector和ArrayList,都是通过数组实现的。
Vector:是线程安全的,因为方法都加了锁的,sychroinzed。因此他访问的时候耗费的时间
更多,效率低。

Vector内部实现原理 add方法
这里写图片描述

ArrayList实现原理
这里写图片描述

2、HashTable

HashMap是线程不安全的,HashTable是线程安全的。加入了锁
HashMap允许null值或键传入。
HashTable是线程安全的,但是效率非常低,因为里面要做锁的资源的竞争。
注意:因为方法是加了sychronized方法的。

多线程共享一个HashTable,每次只能有一个线程去操作这个hashTable

3、sychronizedMap

sychronizedMap:是将线程不安全的集合,变成线程安全的集合。

4、JDK1.5之后发明了ConcurrentHashMap来替代HashTable。

 ConcurrentHashMap:实现原理是使用分段锁来实现的,其是以16段分段底层操作:是将一个整体拆分成多个小的HashTable 默认分成16段。
如图:

这里写图片描述

5、CountDownLatch实现类似计数的功能。

CountDownLatch: 实现类似计数的功能, 比如有个任务A 它要等待其他4 个任务执行完毕后再执行,此时可以使用CountDownLatch

代码演示

package com.leeue.cn;import java.util.concurrent.CountDownLatch;/*** * @classDesc: 功能描述:(CountDownLatch 实现类似计数的功能, 比如有个任务A 它* 要等待其他4 个任务执行完毕后再执行,此时可以使用CountDownLatch)* @author:李月* @Version:v1.0* @createTime:2018年7月23日 下午1:23:33*/
public class CountDownLatchDemo {public static void main(String[] args) throws InterruptedException {//定义个计数器CountDownLatch countDownLatch = new CountDownLatch(2);new Thread(new Runnable() { @Overridepublic void run() {System.out.println("我是子线程1开始执行任务");try {Thread.sleep(10);} catch (Exception e) {// TODO: handle exception}//每次减一countDownLatch.countDown();System.out.println("1子线程开始执行任务结束");}}).start();new Thread(new Runnable() { @Overridepublic void run() {System.out.println("我是子线程2开始执行任务");try {Thread.sleep(10);} catch (Exception e) {// TODO: handle exception}countDownLatch.countDown();System.out.println("2子线程开始执行任务结束");}}).start();countDownLatch.await();//如果>0就不执行下面,就会一直在等待,直到<=0才往下执行System.out.println("主线程开始执行任务");for(int i = 0; i < 10; i++) {System.out.println("main:i"+i);}}
}

程序演示结果
这里写图片描述

6、CyclicBarrier 也是让程序执行完毕再执行需要执行的代码,也是类似计数的功能

CyclicBarrier:CyclicBarrier初始化时规定一个数目, 然后计算调用了CyclicBarrier.await()进入等待的线程数。当线程数达到了这个数目时,所有进入等待状态的线程被唤醒并继续。

代码演示

package com.leeue.cn;import java.util.concurrent.CyclicBarrier;/*** * @classDesc: 功能描述:(* CyclicBarrier初始化时规定一个数目,* 然后计算调用了CyclicBarrier.await()进入等待的线程数。* 当线程数达到了这个数目时,所有进入等待状态的线程被唤醒并继续。)* * 当五个线程执行写入数据完毕过后,再一起执行写入数据成功的语句* @author:李月* @Version:v1.0* @createTime:2018年7月23日 下午1:49:48*/
class Writer extends Thread{private CyclicBarrier cyclicBarrier;public Writer(CyclicBarrier cyclicBarrier) {this.cyclicBarrier = cyclicBarrier;}@Overridepublic void run() {try {System.out.println(Thread.currentThread().getName()+"开始写入数据----");Thread.sleep(30);System.out.println(Thread.currentThread().getName()+"写入数据成功----");cyclicBarrier.await();//并行执行成功System.out.println(Thread.currentThread().getName()+"所有数据执行完毕----");} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}
}
public class CyclicBarrierDemo {public static void main(String[] args) {CyclicBarrier cyclicBarrier = new CyclicBarrier(5);for (int i = 0; i < 5; i++) {new Writer(cyclicBarrier).start();}}
}

执行效果图:
这里写图片描述

7、Semaphore 信号量的使用

Semaphore:是一种基于计数的信号量。它可以设定一个阈值,基于此,
线程申请许可信号将会被阻塞。Semaphore可以用来构建一些对象池,
我们也可以创建计数为1的Semaphore,
将其作为一种类似互斥锁的机制,
这也叫二元信号量,表示两种互斥状态。它的用法如下:
availablePermits函数用来获取当前可用的资源数量其中使用的方法有:
// 最多支持多个资源的访问Semaphore semaphore = new Semaphore(5);// 表示获取到资源权限semaphore.acquire();// 获取到资源后减去1semaphore.availablePermits();// 释放资源semaphore.release();

案例:
需求: 一个厕所只有3个坑位,但是有10个人来上厕所,那怎么办?假设10的人的编号分别为1-10,并且1号先到厕所,10号最后到厕所。那么1-3号来的时候必然有可用坑位,顺利如厕,4号来的时候需要看看前面3人是否有人出来了,如果有人出来,进去,否则等待。同样的道理,4-10号也需要等待正在上厕所的人出来后才能进去,并且谁先进去这得看等待的人是否有素质,是否能遵守先来先上的规则。

代码

package com.leeue.cn;import java.util.Random;
import java.util.concurrent.Semaphore;/*** * @classDesc: 功能描述:(Semaphore 信号量 也是类似计数的功能 )* @author:李月* @Version:v1.0* @createTime:2018年7月23日 下午2:07:39*/
class Parent implements Runnable {Semaphore wc;String name;public Parent(Semaphore wc, String name) {this.wc = wc;this.name = name;}@Overridepublic void run() {try {// 获取到资源 减1int availablePermits = wc.availablePermits();//System.out.println(availablePermits);if (availablePermits > 0) {System.out.println(name+"天助我也!我有茅坑了!");} else {System.out.println(name+"怎么没有茅坑了!");}//表示获取到了茅坑资源wc.acquire();System.out.println(name+"我终于能上厕所了!");//模拟上厕所用的时间Thread.sleep(new Random().nextInt(1000));System.out.println(name+"厕所终于上完了");} catch (Exception e) {e.printStackTrace();}finally {//释放资源wc.release();}}
}public class SemaphoreDemo {/* 基本用法// 最多支持多个资源的访问Semaphore semaphore = new Semaphore(5);// 表示获取到资源权限semaphore.acquire();// 获取到资源后减去1semaphore.availablePermits();// 释放资源semaphore.release();*/public static void main(String[] args) throws InterruptedException {Semaphore semaphore =  new Semaphore(3);for(int i = 1; i <= 10; i++) {new Thread(new Parent(semaphore, "我是第"+i+"人")).start();}}
}

8、并发队列ConcurrentLinkedDeque

分析:

这里写图片描述
并发队列
有界队列:
无界队列:
在并发队列中有界、无界区别在于一个支持有限制,一个无限制

所有的队列都是实现接口:Deque

 无界安全队列:ConcurrentLinkedDeque使用方法:
package com.leeue.cn;import java.util.concurrent.ConcurrentLinkedDeque;/*** 无界安全队列* @classDesc: 功能描述:(并发队列 ConcurrentLinkedDeque 队列是先进先出,后进后出原则)* @author:李月* @Version:v1.0* @createTime:2018年7月23日 下午3:15:24*/
public class ConcurrentLinkedDequeDemo {public static void main(String[] args) {//无界队列 就是没有限制的队列 无限进入存储的队列ConcurrentLinkedDeque concurrentLinkedDeque = new ConcurrentLinkedDeque();concurrentLinkedDeque.offer("张三");//增加一个concurrentLinkedDeque.offer("李四");System.out.println(concurrentLinkedDeque.poll());// 取出一个长度会减一System.out.println(concurrentLinkedDeque.peek());//取出一个,但是长度不会减一System.out.println("长度"+concurrentLinkedDeque.size());}
}

9、BlockingQueue阻塞队列

阻塞队列:当生产者写入满的时候,就会进入阻塞。当队列为空的时候,消费者也会等待。
和非阻塞队列:
区别:

说明白这些:

这里写图片描述

10、使用BlockQueue模拟生产者与消费者


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部