1. 概述:
是JDK1.5提供的一套用于高并发和保证线程安全的包:
- java.until.concurrent---高并发
- java.until.concurrent.lock 线程锁
- java.until.concurrent.atomic 原子性
2. 5套接口:
2.1 Blockingqueue---阻塞式双向队列
特点:
- 阻塞 ---FIFO 先进先出
- 这个队列必须有界---容量指定之后,不可变
- 若此时队列为空,视图获取元素的线程会被阻塞反之,试图放入元素的线程就会被阻塞
public interface BlockingQueue
实现类:
1.ArrayBlockingQueue---阻塞是顺序队列
a.底层是基于数组实现---指定大小,大小不可变
b.若此时返回值为null,证明当前队列为空
阻塞是队列,添加元素null,会抛出空指针异常
使用场景:生产消费模型
c.重要方法:
| 抛出异常 | 返回值 | 永久阻塞 | 定时阻塞 | |
| 添加 | add | offer--true/false | put | offer |
| 获取 | remove | poll--null | take | poll |
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;
public class ArrayBlocakingDemo01 {
public static void main(String[] args) throws InterruptedException {
//指定底层数组容量
ArrayBlockingQueue queue = new ArrayBlockingQueue<>(3);
//1.添加元素
queue.add(null);
//队列以满 抛出异常
//队列已满,返回false
//boolean b = queue.offer("b");
//System.out.println(b);
//队列已满 阻塞--若没有获取队列元素就会永久阻塞
//queue.put("a");
//定时阻塞
boolean b = queue.offer("d",5, TimeUnit.SECONDS);
System.out.println(queue);
//此时队列为空,抛出异常
//System.out.println(queue.remove());
//此时队列为空,返回null
//System.out.println(queue.poll());
//此时队列为空,没有元素 永久阻塞
//System.out.println(queue.take());
//定时阻塞
//System.out.println(queue.poll(5,TimeUnit.SECONDS));
}
}
2.linkedBlockingQueue---链式阻塞式队列
a.底层是基于节点实现---有界的
public linkedBlockingQueue() {
this(Integer.MAX_VALUE);
}
创建该队列的时候,可以指定也可以不指定大小,指定的话,大小不可变;反之,则默认值为Integer.MAX_VALUE(0x7fffffff);一般认为该队列无界
| 永久阻塞 | 定时阻塞 |
| put | offer |
| take | poll |
import java.util.concurrent.linkedBlockingQueue;
public class linkedBlocakingDemo01 {
public static void main(String[] args) throws InterruptedException {
//指定底层数组容量
linkedBlockingQueue queue = new linkedBlockingQueue(3);
//1.添加元素
queue.add("a");
queue.add("B");
queue.add("C");
//队列以满 抛出异常
//队列已满,返回false
boolean b = queue.offer("b");
//System.out.println(b);
//队列已满 阻塞--若没有获取队列元素就会永久阻塞
queue.put("a");
//定时阻塞
System.out.println(queue);
//此时队列为空,抛出异常
//System.out.println(queue.remove());
//此时队列为空,返回null
//System.out.println(queue.poll());
//此时队列为空,没有元素 永久阻塞
//System.out.println(queue.take());
//定时阻塞
//System.out.println(queue.poll(5,TimeUnit.SECONDS));
}
}
3.priorityBlockingQueue---具有优先级
a. private static final int DEFAULT_INITIAL_CAPACITY = 11;
在使用的时候可以指定的大小,也可以不指定,初始大小为11
b.private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
此时容量用满之后,最大容量是Integer.MAX_VALUE - 8
c.private transient Object[] queue; 底层靠数组存储元素
d.在遍历队列的时候,会将放入队列的元素进行自然排序
e.若当前队列存储对象,进行排序,会抛出类型转换异常:需要当前对象必须实现一个Comparable接口; 若遍历元素,使用迭代遍历不能保证顺序
package cn.tedu;
import java.util.concurrent.linkedBlockingQueue;
import java.util.concurrent.PriorityBlockingQueue;
public class PriorityBlocakingDemo01 {
public static void main(String[] args) throws InterruptedException {
//指定底层数组容量
PriorityBlockingQueue queue = new PriorityBlockingQueue();
//PriorityBlockingQueue queue = new PriorityBlockingQueue();
queue.put("a");
queue.put("b");
queue.put("e");
queue.put("c");
queue.put("d");
for (String s:queue) {
System.out.println(s);
}
}
}
class Stu implements Comparable{
private String name;
private int age;
private int score;
public Stu() { }
public Stu(String name, int age, int score) {
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 "Stu{" +
"name='" + name + ''' +
", age=" + age +
", score=" + score +
'}';
}
@Override
public int compareTo(Stu o) {
return this.age-o.age;
}
}
1.SynchonousQueue---同步时队列
再定义的时候,根本不需要指定容量,因为容量为1
会把这个队列作为汇合点
2.2 concurrentMap --- 并发映射
是jdk1.5提供的用于保证高并发和线程安全的映射机制
hashmap---异步式线程不安全映射---》数组+链表
ConcurrentHashMap---并发哈希映射---》底层基于数组+链表存储数据,数组的每一个位置都是桶(bucket)结构,每一个桶中维系一个链表
默认初始容量是16(指的是数组的初始长度,并不代表当前映射只能存储16个元素,加载因子0.75--》已用桶的个数/总的桶的个数>加载因子,就会扩容,每次会扩容1倍,扩容之后,会将元素重新分布)
最终的容量一定是2^n,最大容量是2^30
在1.8之前底层采用的是分桶锁机制(分段锁),在此基础上添加了读写锁(1.7出现)
读锁:允许多个线程的读,不允许线程的写
写锁:只允许一个线程写,不允许读
官方解释:我认为V的值应该是A,如果是,那么此时将V 的值更新为B,否则不修改并告诉V实际值是多少
CAS在执行过程中如果被打断,就会从头开始执行
1.所有的节点颜色非红即黑
2.根节点必须是黑色
3.红色的子节点一定是黑色,黑节点的子节点可以是黑的也可以是红的
4.最底层的叶子节点一定时空的---nil
5.从根节点到任意一个叶子节点经过的黑节点个数一定相同
6.新添加的节点颜色必须是红色
1.涂色:当前节点为红父节点,并且叔父节点为红,那么就需要将父节点以及叔父节点涂黑,将祖父节点涂红
2.左旋:当前节点为红,父节点为红,叔父叔父节点为黑
3.右旋:当前节点为红父节点也为红,叔父节点为黑并且当前节点为左子叶,就会按照父级节点为轴,进行右旋
4.当桶中元素超过8个,会转换成一个红黑树结构;如果节点个数不足7,会重新扭转成一个链式结构,这个过程称之为树化
ExecutorService ---执行器服务
做到资源的重用
做到资源的重用
就是存储线程资源的队列
临时线程使用完毕之后,不会被立即销毁,而是会存活一段时间,如果该时间段没有请求,就会被销毁
lock atomic
- Callable
- 如果此时临时线程也全部被占用,则后续的请求就会交给拒绝执行处理器来进行拒绝处理
- 如果工作队列和核心线程资源都被占用,新来的请求会被交给临时线程处理---与核心线程唯一的区别就是用完就销毁
- 在核心线程数量达到指定数量之前,每次请求都会创建新的
- 核心线程使用完成之后不会被销毁,而是等待下一个任务
- 如果核心线程成都被占用,则后续的请求会被放到一个工作队列中(阻塞式队列)
- 每过来一个请求,都会创建一个线程去处理这个请求,直到线程数达到指定的数量不在创建为止,这些线程称之为核心线程
- 线程池:访问服务端会产生大量的连接和销毁,避免对资源的浪费---减少连接和销毁的过程
- 连接池:访问数据库会有大量的连接和销毁,避免对资源的浪费---减少连接和销毁的过程
- 修正
- 红黑树
- 本质上是一个自平衡的二叉查找树(B树/B-树、B+树)
- 特点:
- 1.8及其之后,又做了优化,引入了无锁算法(降低锁对资源的消耗)---CAS(比较和交换)
- jdk1.8之前,向链表中插入数据时头插法,在此之后,使用的尾插法
- SynchonousQueue---同步时队列
- priorityBlockingQueue---具有优先级
- linkedBlockingQueue---链式阻塞式队列
- ArrayBlockingQueue---阻塞是顺序队列
- 重要方法‘
- 阻塞 ---FIFO 先进先出
- 这个队列必须有界---容量指定之后,不可变
- 若此时队列为空,视图获取元素的线程会被阻塞
- java.until.concurrent---高并发
- java.until.concurrent.lock 线程锁
- java.until.concurrent.atom



