集合类不安全(unSale)

集合类不安全(unSale)

1:List不安全

package com.baidu.unSale;

import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;

/*
java.util.ConcurrentModificationException  并发修改异常
 */
public class ListTest {
    public static void main(String[] args) {

        //并发情况下:ArrayList  是不安全的;
        /**
         * 解决:
         * 1: List<String> list = new Vector<>();    Vector<></>
         * 2:List<String> list = Collections.synchronizedList(new ArrayList<>());
         * 3:List<String> list = new CopyOnWriteArrayList<>();
         *
         * CopyOnWrite 写入时复制 COW 计算机程序设计领域的一种优化策略:
         * 多个线程在调用的时候,list  读取的时候是固定的,写入(覆盖)
         * 在写入的时候避免覆盖,造成数据问题,。
         *
         * CopyOnWriteArrayList 比 Vector 厉害在哪里;
         * 1:Vector 用的是Synchronized 效率比Lock锁低;
         * 2:CopyOnWriteArrayList 用的是Lock锁
         */

        List<String> list = new CopyOnWriteArrayList<>();


        for (int i = 1; i < 10; i++) {
            new Thread(()->{
                list.add(UUID.randomUUID().toString().substring(0,5));
                System.out.println(list);
            },String.valueOf(i)).start();
        }
    }
}

2:Set 不安全的

package com.baidu.unSale;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArraySet;

/*
同理:看LisetTest 类

java.util.ConcurrentModificationException 并发修改异常

解决:
    1:工具类的方法:
        Set<String> set = Collections.synchronizedSet(new HashSet<>());

    2: JUC 解决方法;

 */
public class SetTest {

    public static void main(String[] args) {

//        Set<String> set = new HashSet<>();
//        Set<String> set = Collections.synchronizedSet(new HashSet<>());
        Set<String> set = new CopyOnWriteArraySet<>();

        for (int i = 0; i < 30; i++) {
            new Thread(()->{
                set.add(UUID.randomUUID().toString().substring(0,5));
                System.out.println(set);
            }).start();
        }

    }
}

HashSet的底层是什么?
在这里插入图片描述
HashSet的底层就是一个Hash Map
HashSet 的 add 方法, Set 本质上就是Map 的key ,因为key是无法重复的;

在这里插入图片描述

3:Map是不安全的

在这里插入图片描述

在这里插入图片描述

package com.baidu.unSale;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

/**
 * java.util.ConcurrentModificationException  并发修改异常;
 *
 * 解决:  
 *  1;是否有工具类
 *      Map<String, String> map = Collections.synchronizedMap(new HashMap<>());
 *
 */
public class MapTest {

    public static void main(String[] args) {

        //map,是这样用的吗??  不是,工作中是不会用HashMap
        //默认等价与什么?   new HashMap<>(16,0.75);
        // 加载因子   初始化的容量

        //思考: 研究ConcurrentHashMap 的yuan'liyuan'li
//        Map<String, String> map = new HashMap<>();
        Map<String, String> map = new ConcurrentHashMap<>();


        for (int i = 1; i < 1000; i++) {
            new Thread(()->{
                map.put(Thread.currentThread().getName(), UUID.randomUUID().toString().substring(0,5));
                System.out.println(map);
            }).start();
        }

    }
}

常用的辅助类 (add)

在这里插入图片描述

1:CountDownLatch

package com.baidu.add;

import java.util.concurrent.CountDownLatch;

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

        CountDownLatch countDownLatch = new CountDownLatch(6);

        for (int i = 1; i <=6; i++) {
            new Thread(()->{
                System.out.println(Thread.currentThread().getName()+"Get Out");
                countDownLatch.countDown(); //数量减一1
            },String.valueOf(i)).start();
        }

        countDownLatch.await(); //等待计数器为零 ,然后在往下执行;

        System.out.println("Close Door");
    }

}

原理:

countDownLatch.countDown(); //数量减一1
countDownLatch.await(); //等待计数器为零 ,然后在往下执行;

2:CyclicBarrier

在这里插入图片描述

package com.baidu.add;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierDemo {

    public static void main(String[] args) {

        CyclicBarrier cyclicBarrier = new CyclicBarrier(7,()->{
            System.out.println("召唤神龙成功!");
        });


        for (int i = 1; i <= 7; i++) {

            final int temp = i;


            new Thread(()->{
                System.out.println(Thread.currentThread().getName()+"收集"+temp+"个龙珠.");

                try {
                    cyclicBarrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}

3:Semaphore

package com.baidu.add;

import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

public class SemaphoreDemo {

    public static void main(String[] args) {

        //线程数量,停车位.限流!!
        Semaphore semaphore = new Semaphore(3);

        for (int i = 1; i <= 6; i++) {
           new Thread(()->{
               //acquire()得到
               try {
                   semaphore.acquire();
                   System.out.println(Thread.currentThread().getName()+"抢到车位");
                   TimeUnit.SECONDS.sleep(2);
                   System.out.println(Thread.currentThread().getName()+"离开车位");
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }finally {
                   //release()释放
                   semaphore.release();
               }
           },String.valueOf(i)).start();
        }
    }
}

原理:

 semaphore.acquire(); 获得;假设已经满了,等待,等待被释放为止;
 semaphore.release(); 释放,会将当前的释放量释放+1;然后唤醒等待的线程。
 

作用:
多个共享的资源互斥的使用!并发限流,控制最大的线程数!

ReentrantReadWriteLock (ReadWriteLock)读写锁

加读写锁;是为了多条线程可以同时读取,写的时候只能允许只有一条线程进行写入操作。

在这里插入图片描述

package com.baidu.ReadWriteLock;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class ReadWriteLockDemo {

    public static void main(String[] args) {
        //MyCache myCache = new MyCache();  //读写乱套,

        MyCacheLock myCache = new MyCacheLock();

        for (int i = 1; i <= 5; i++) {
            final int temp = i;
            new Thread(()->{
                myCache.put(temp+"",temp+"");
            },String.valueOf(i)).start();
        }

        for (int i = 1; i <= 5; i++) {
            final int temp = i;
            new Thread(()->{
                myCache.get(temp+"");
            },String.valueOf(i)).start();
        }

    }
}
class MyCacheLock{

    public volatile Map<String,Object> map = new HashMap<>();

    //读写锁
    private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

    //存,,写入操作
    public void put(String key,Object value){

        readWriteLock.writeLock().lock();

        try {
            System.out.println(Thread.currentThread().getName()+"写入"+key);
            map.put(key, value);
            System.out.println(Thread.currentThread().getName()+"写入OK");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            readWriteLock.writeLock().unlock();
        }


    }

    //取,读取操作
    public void get(String key){

        readWriteLock.readLock().lock();

        try {
            System.out.println(Thread.currentThread().getName()+"读取"+key);
            map.get(key);
            System.out.println(Thread.currentThread().getName()+"读取OK"+key);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            readWriteLock.readLock().unlock();
        }



    }
}

//自定义缓存;
class MyCache{

    public volatile Map<String,Object> map = new HashMap<>();

    //存,,写入操作
    public void put(String key,Object value){
        System.out.println(Thread.currentThread().getName()+"写入"+key);
        map.put(key, value);
        System.out.println(Thread.currentThread().getName()+"写入OK");
    }

    //取,读取操作
    public void get(String key){
        System.out.println(Thread.currentThread().getName()+"读取"+key);
        map.get(key);
        System.out.println(Thread.currentThread().getName()+"读取OK"+key);


    }
}

阻塞队列BlockingQueue (BlockingQueue)在这里插入图片描述
在这里插入图片描述
什么情况下我们会使用阻塞队列:多线程并发处理。线程池;
学会使用队列;
添加,移除

在这里插入图片描述
1:抛出异常

 /**
     * 1:抛出异常
     */
    public static void test1(){

        //队列的大小
        ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);

        System.out.println(blockingQueue.add("a"));
        System.out.println(blockingQueue.add("b"));
        System.out.println(blockingQueue.add("c"));

//        java.lang.IllegalStateException: Queue full 抛出异常
//        System.out.println(blockingQueue.add("d"));

        System.out.println(blockingQueue.element());//对首

        System.out.println("=======================");

        System.out.println(blockingQueue.remove());
        System.out.println(blockingQueue.remove());
        System.out.println(blockingQueue.remove());

//        java.util.NoSuchElementException  抛出异常
//        System.out.println(blockingQueue.remove());

    }

2:不抛出异常

/**
 * 2;有返回值,没有异常
 */

public static void test2(){

    //队列的大小
    ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);

    System.out.println(blockingQueue.offer("a"));
    System.out.println(blockingQueue.offer("b"));
    System.out.println(blockingQueue.offer("c"));

    //返回一个Boolean值; false;
    System.out.println(blockingQueue.offer("d"));

    System.out.println(blockingQueue.peek()); //对首
    System.out.println("===========================");

    System.out.println(blockingQueue.poll());
    System.out.println(blockingQueue.poll());
    System.out.println(blockingQueue.poll());

    //返回一个Null;
    System.out.println(blockingQueue.poll());


}

3:阻塞等待

/**
 *3:等待  阻塞(一直阻塞)
 */

public static void test3() throws InterruptedException {
    ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);

    //一直阻塞
    blockingQueue.put("a");
    blockingQueue.put("b");
    blockingQueue.put("c");

   // blockingQueue.put("d");//队列没有位置了

    System.out.println("=========================");

    System.out.println(blockingQueue.take());
    System.out.println(blockingQueue.take());
    System.out.println(blockingQueue.take());

    //System.out.println(blockingQueue.take());//没有这个元素,一直阻塞



}

4:超时等待

/**
 *4:等待  阻塞(等待超时)
 */
public static void test4() throws InterruptedException {
    ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);

    System.out.println(blockingQueue.offer("a"));
    System.out.println(blockingQueue.offer("b"));
    System.out.println(blockingQueue.offer("c"));
    blockingQueue.offer("d",2,TimeUnit.SECONDS);//等待超时 2 秒退出

    System.out.println("=====================");

    System.out.println(blockingQueue.poll());
    System.out.println(blockingQueue.poll());
    System.out.println(blockingQueue.poll());
    System.out.println(blockingQueue.poll(2, TimeUnit.SECONDS));
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值