Map/Set的使用
正常使用,不需要并发加锁:
HashMap/HashSet
TreeMap/set:底层红黑树,默认排好序
LinkedHashMap/set
低并发:
HashTable
Conlections.synchronizedxxx
高并发:
CurrentHashMap
CurrentSkipListMap:有顺序
队列
不加锁:
arraylist
Linklist
Conlections.synchronizedxxx
CopeWriteList:每次写数据都会copy一份原来的数据然后在该数据基础上写数据,不用加锁,适用于读多写少的情况
Queuen:
ConcurrentLinkedQueue:
Queue <String>queue=new ConcurrentLinkedQueue();
String i = queue.poll();//具有原子性,取出操作,没有值返回空
BlockingQueue:LinkedBlockingQueue//无界容器 ArrayBlockingQueue(有界容器)
BlockingQueue <Integer> queue=new LinkedBlockingQueue<>();//无界容器,除非内存满了不然可以一直加
ArrayBlockingQueue(有界容器)
private static BlockingQueue<Integer> queue=new ArrayBlockingQueue<>(10);
public static void main(String[] args) {
for(int i=0;i<10;i++){
queue.add(i);
}
//queue.add(555);//add方法越界添加会报异常;
//boolean flag=queue.offer(555);//offer方法越界添加不会报异常,会返回一个boolean值通知是否成功
try {
// boolean flag=queue.offer(555,1,TimeUnit.SECONDS);//等待指定时间看看能否添加成功
// System.out.println(flag);
}catch (Exception e){
e.printStackTrace();
}
}
LinkedTransferQueue
private static LinkedTransferQueue <String>queue=new LinkedTransferQueue<>() ;
public static void main(String[] args) {
try {
queue.transfer("aaa");//直接将资源交给需要的线程,不存入容器,没找到需要资源的线程就一直阻塞
System.out.println("hahah");
}catch (Exception e){
e.printStackTrace();
}
new Thread(()->{
try {
queue.take();
}catch (Exception e){
e.printStackTrace();
}
},"t1").start();
}
SynchronousQueue
private static BlockingQueue <String>queue=new SynchronousQueue<>();
public static void main(String[] args) {
// queue.add("aaa");//会报错,因为SynchronousQueue是一个没有容量的容器,他只能直接将资源交给需要资源的线程
try {
queue.put("aaa");//不会报错,内部采用tachsferqueuen的transfer()方法,没有线程请求资源,会一直阻塞
System.out.println("hahah");
}catch (Exception e){
e.printStackTrace();
}
}
锁(Lock)
Lock lock=new ReentrantLock();//synchronized在遇到异常时jvm会释放锁,lock不会必须手动释放锁
try{
lock.lock();
for(int i=0;i<10;i++){
System.out.println(i);
Thread.sleep(500);
}
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
package com.yc.lock;
import java.util.LinkedList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class CustomAndProduce<T> {
private LinkedList<T> list = new LinkedList<T>();
private final static int Max = 10;
private final static int Min = 0;
Lock lock = new ReentrantLock();
Condition p = lock.newCondition();
Condition c = lock.newCondition();
public void put(T i) {
try {
lock.lock();
while (list.size() == Max) {
p.await();
}
list.add(i);
c.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public T get() {
try {
lock.lock();
while (list.size() == Min) {
c.await();
}
T t = list.removeFirst();
p.signalAll();
return t;
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
lock.unlock();
}
}
public static void main(String[] args) {
CustomAndProduce cap=new CustomAndProduce();
for(int i=0;i<5;i++){
new Thread(()->{
for(int j=0;j<Max;j++){
cap.put(j);
System.out.println(Thread.currentThread().getName()+":"+j);
}
},"p"+i).start();
}
for(int i=0;i<2;i++){
new Thread(()->{
for(int j=0;j<Max;j++)
{
int a= (int) cap.get();
System.out.println(Thread.currentThread().getName()+"a:"+a);
}
},"c"+i).start();
}
}
}
这种方式可以精确选择唤醒的时生产者线程还是消费者线程
门栓(CountDownLatch)
new CountDownLatch(1)设置次数,次数减到0时await()的对象被唤醒,没执行一次目标操作就 countDown();将数量减一
package com.yc.lock;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
public class Test06 {
private volatile List<Object> list=new ArrayList<>();
public void add(Object obj){
list.add(obj);
}
public int size(){
return list.size();
}
public static void main(String[] args) {
Test06 t=new Test06();
// Runnable a=()->t.size();
// Runnable b=t::size;
CountDownLatch downLatch=new CountDownLatch(1);
new Thread(()->{
if(t.size()!=5) {
try {
downLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("t2结束");
},"t2").start();
new Thread(()->{
for(int i=0;i<10;i++){
System.out.println("size:"+t.list.size());
t.add(new Object());
if(t.size()==5){
downLatch.countDown();
}
}
System.out.println("t1结束");
},"t1").start();
}
}