java高并发之Councurrent详解

本文深入探讨了Java并发编程中的Concurrent包,涵盖了阻塞式队列BlockingQueue,包括ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue和SynchronousQueue,以及并发映射ConcurrentMap如HashMap、HashTable和ConcurrentHashMap。文章还讨论了锁机制如CountDownLatch、CyclicBarrier、Exchanger、Semaphore、Lock和ReadWriteBarrier,线程池的概念,以及多线程的意义和提高CPU利用率的重要性。
摘要由CSDN通过智能技术生成

最近将自己之前的知识整理整合一遍,防止遗漏忘记。

Concurrent

concurrent包是jdk1.5开始所提供的一个针对高并发进行编程的包。

一.阻塞式队列 - BlockingQueue

遵循先进先出(FIFO)原则。阻塞式队列本身使用的时候需要指定界限。

1.ArrayBlockingQueue-阻塞式顺序队列

底层是基于数组来进行储存的,使用时需要指定一个容量,容量在指定之后不可改变。多用于生产-消费模型。
示例代码:

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

		// 这个队列在创建的时候需要指定容量,容量在指定之后不可变
		ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<>(5);

		// 添加队列
		queue.add("a");
		queue.add("b");
		queue.add("c");
		queue.add("d");
		queue.add("e");

		// 如果队列已满,则抛出异常 - IllegalStateException
		// queue.add("a");
		// 返回值标记元素是否成功添加到队列里面
		// 如果队列已满,则返回false
		// boolean b = queue.offer("b");
		// System.out.println(b);
		// 如果队列已满,会产生阻塞 --- 直到这个队列中有元素被取出,才会放开阻塞
		// queue.put("c");
		// 队列为空,抛出异常:NoSuchElementException
		// String str = queue.remove();
		// 队列为空,返回null
		// String str = queue.poll();
		// 队列为空,产生阻塞 - 直到有其他线程向队列中添加元素,才会放开阻塞
		// String str = queue.take();
		// 定时阻塞
		// 在3s之内如果有元素被取出,那么元素就会添加到队列中
		// 如果3s之后队列依然是满的,那么返回false表示添加失败
		boolean b = queue.offer("d", 3000, TimeUnit.MILLISECONDS);
		System.out.println(b);
		System.out.println(queue);
	}
2.LinkedBlockingQueue-阻塞式链式队列

底层时基于链表(节点)来进行数据的储存。在使用的时候可以指定初始容量,也可以不指定。如果指定了容量,就以指定的容量为准来进行储存;如果不指定容量,默认容量是Integer.MAX_VALUE->2^31-1,一般认为这个容量是无限的。

3.PriorityBlockingQueue-具有优先级的阻塞式队列

如果不指定容量,默认容量是11.如果将元素依次取出,那么会对元素进行自然排序,要求存储的对象对应的类必须实现Comparable类,重写compareTo方法,将自定的比较规则写入方法中;如果进行迭代遍历,则不会保证排序。
示例代码:

public class PriorityBlockingQueueDemo2 {
   

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

		PriorityBlockingQueue<Student> queue = new PriorityBlockingQueue<>();

		queue.put(new Student("程咬金", 15, 59));
		queue.put(new Student("秦琼", 18, 89));
		queue.put(new Student("王世充", 80, 48));
		queue.put(new Student("李元霸", 12, 90));
		
		
		for (Student s : queue) {
   
			System.out.println(s);
		}
		
		for(int i = 0; i < 4; i++){
   
			System.out.println(queue.take());
		}

	}

}

class Student implements Comparable<Student>{
   

	private String name;
	private int age;
	private int score;

	public Student(String name, int age, int score) {
   
		super();
		this.name = name;
		this.age = age;
		this.score = score;
	}

	public String getName() {
   
		return name;
	}

	public void setName(String name) {
   
		this.name = name;
	}

	public int getAge() {
   
		return age;
	}

	public void setAge(int age) {
   
		this.age = age;
	}

	public int getScore() {
   
		return score;
	}

	public void setScore(int score) {
   
		this.score = score;
	}

	@Override
	public String toString() {
   
		return "Student [name=" + name + ", age=" + age + ", score=" + score + "]";
	}

//	@Override
//	// 指定比较规则
//	// 如果返回值>0,那么this就要排到o的后边
//	// 如果返回值<0,那么this就要排到o的前边
//	public int compareTo(Student o) {
   
//		return this.age - o.age;
//	}

	@Override
	public int compareTo(Student o) {
   
		return o.score - this.score;
	}
	
}
4.SynchronousQueue-同步队列

队列只允许存储一个元素。

二.并发映射 - ConcurrentMap

1.hashMap

底层依靠数组加链表储存的数据。默认初始容量是16,默认加载因子是0.75f,默认扩容每次增加一倍。本身是一个异步式线程不安全的映射。

2.HashTable

同步式线程安全的映射,对外提供的方法都是同步方法。

3.ConcurrentHashMap

异步式线程安全的映射,在jdk1.8之前采用分段锁,分段锁采用的式读写锁机制(读锁:允许多个线程读,但不允许线程写;写锁:允许一个线程写,但不允许线程读),jdk1.8不再采用锁机制,而是CAS(Compare and Swap)算法,减少了锁的开销。如果一个段(桶)中的元素超过了8个,那么会将这个段(桶)的链表扭转成一棵红黑树(自平衡二叉查找树)结构。
自平衡二叉树

补充:红黑树的修正过程

1.当前节点为红色,且父节点以及叔父节点为红色,那么将父节点以及叔父节点但涂黑,将祖父节点涂红。
2.当前节点为红色,并且是右子叶,父节点为红且叔父节点为黑,那么以当前节点为基准进行左旋。
3.当前节点为红色,并且是左子叶,父节点为红且叔父节点为黑,那么以父节点为基准进行右旋。
红黑树的查找的时间复杂度为:O(logn)。

ConcurrentNavigableMap - 并发导航映射

其本身为一个接口,所以更多的是使用实现类—ConcurrentSkipListMap–并发跳跃表映射
跳跃表:为了提高查询效率所产生的一种数据结构—跳跃表是典型的以空间换时间的产物。
跳跃表
如果跳跃表中插入新的元素,新的元素是否往上提取遵循“抛硬币”原则–二分之一原则,只要保证这个节点有一半的概率被提取就可以了。所以跳跃表一般只适合大量查询而不增删的场景。

三.锁

CountDownLatch-闭锁

线程递减锁,对线程进行技术,当计数归零的时候会放开阻塞让线程继续往下执行。
CountDownLatch

public class CountDownLatchDemo {
   
	
	public static void main(String[] args) throws InterruptedException {
   
		
		CountDownLatch cdl = new CountDownLatch(5);
		
		new Thread(new Teacher(cdl)).start
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值