JUC 概述 ---1

目录

1. 概述: 

2. 5套接口:

2.1 Blockingqueue---阻塞式双向队列 

2.2  concurrentMap --- 并发映射


1. 概述: 

是JDK1.5提供的一套用于高并发和保证线程安全的包:

  • java.until.concurrent---高并发
  • java.until.concurrent.lock  线程锁
  • java.until.concurrent.atomic  原子性

2. 5套接口:

2.1 Blockingqueue---阻塞式双向队列 

特点:

  • 阻塞  ---FIFO  先进先出
  • 这个队列必须有界---容量指定之后,不可变
  • 若此时队列为空,视图获取元素的线程会被阻塞反之,试图放入元素的线程就会被阻塞

             

             public interface BlockingQueue<E> extends Queue<E>

实现类:

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<String> queue = new ArrayBlockingQueue<>(3);
        //1.添加元素
        queue.add(null);
       /* queue.add("B");
        queue.add("C");*/
        //队列以满 抛出异常
        /*queue.add("C");*/
        //队列已满,返回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");
        //队列以满 抛出异常
        /*queue.add("C");*/


        //队列已满,返回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));

    }



}

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.在遍历队列的时候,会将放入队列的元素进行自然排序,增强for循环会顺着输入顺序打印。

 e.若当前队列存储对象,进行排序,会抛出类型转换异常:需要当前对象必须实现一个Comparable接口; 若遍历元素,使用迭代遍历不能保证顺序

 

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.PriorityBlockingQueue;
public class PriorityBlocakingDemo01 {
    public static void main(String[] args) throws InterruptedException {
        //指定底层数组容量
       PriorityBlockingQueue<String> queue = new PriorityBlockingQueue();
        //PriorityBlockingQueue<Stu> queue = new PriorityBlockingQueue();
       queue.put("a");
        queue.put("b");
        queue.put("e");
        queue.put("c");
        queue.put("d");
        /*queue.add(new Stu("亚洲舞王赵四",18,80));
        queue.add(new Stu("战神王老七",19,75));*/
       /* for (int i=0;i<5;i++){
            System.out.println(queue.take());

        }*/

       for (String s:queue) {

            System.out.println(s);
        }

    }

}

class Stu implements Comparable<Stu>{

    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;
    }
}

 4.SynchonousQueue---同步时队列

再定义的时候,根本不需要指定容量,因为容量为1

会把这个队列作为汇合点

2.2  concurrentMap --- 并发映射

1.是jdk1.5提供的用于保证高并发和线程安全的映射机制

2.hashmap---异步式线程不安全映射--->数组+链表

3.ConcurrentHashMap---并发哈希映射--->底层基于数组+链表存储数据,数组的每一个位置都是桶(bucket)结构,每一个桶中维系一个链表

4.默认初始容量是16(指的是数组的初始长度,并不代表当前映射只能存储16个元素,加载因子0.75--》已用桶的个数/总的桶的个数>加载因子,就会扩容(

private static final int tableSizeFor(int c) {
    int n = c - 1;
    n |= n >>> 1;
    n |= n >>> 2;
    n |= n >>> 4;
    n |= n >>> 8;
    n |= n >>> 16;
    return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}

),每次会扩容1倍,扩容之后,会将元素重新分布)

最终的容量一定是2^n,最大容量是2^30

5.  1).在1.8之前底层采用的是分桶锁机制(分段锁),在此基础上添加了读写锁(1.7出现)

       读锁:允许多个线程的读,不允许线程的写

      写锁:只允许一个线程写,不允许读

    2).1.8及其之后,又做了优化,引入了 无锁算法 (降低锁对资源的消耗)---CAS(比较和交换)

    官方解释:我认为V的值应该是A,如果是,那么此时将V 的值更新为B,否则不修改并告诉V实       际值是多少

        CAS在执行过程中如果被打断,就会从头开始执行

3).红黑树

本质上是一个 自平衡 二叉查找树(B树 /B- 树、 B+ 树)

1.所有的节点颜色非红即黑

2.根节点必须是黑色

3.红色的子节点一定是黑色,黑节点的子节点可以是黑的也可以是红的

4.最底层的叶子节点一定时空的---nil

5.从根节点到任意一个叶子节点经过的黑节点个数一定相同

6.新添加的节点颜色必须是红色

修正:

1.涂色:当前节点为红父节点,并且叔父节点为红,那么就需要将父节点以及叔父节点涂黑,将祖父节点涂红

2.左旋:当前节点为红,父节点为红,叔父叔父节点为黑

3.右旋:当前节点为红父节点也为红,叔父节点为黑并且当前节点为左子叶,就会按照父级节点为轴,进行右旋

4.当桶中元素超过8个,会转换成一个红黑树结构;如果节点个数不足7,会重新扭转成一个链式结构,这个过程称之为树化

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值