集合类不安全(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:抛出异常
*/
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));
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/71876.html