目录
1. HashTable & Vector2. ConcurrentHashMap3. ConcurrentMap4. CopyOnWrite5. LinkedBlockingQueue6. ArrayBlockingQueue7. DelayQueue8. SynchronousQueue9. TransferQueue
1. HashTable & Vector
HashTable实现了Map接口,Vector实现了List接口HashTable和Vector的所有方法都加了synchronized,这两个容器基本不用HashMap完全没加锁Collections类里的synchronizedMap方法会给HashMap加锁,效率和HashTable的区别不大Collections类里的synchronizedList可以给List加锁
2. ConcurrentHashMap
在多线程中使用的Map读数据效率很高插入数据时,java8之前使用链表,8之后使用红黑树,有很多cas的判读但,所以插入效率比较低
3. ConcurrentMap
ConcurrentHashMap的有序版本为使用跳表实现的ConcurrentSkipListMap
4. CopyOnWrite
CopyOnWriteLIst/CopyOnWriteSet写时复制:添加元素的时候,先把原容器内的元素复制,把老容器的引用指向新容器无需加锁,写的效率比较低,读的时候不用加锁,效率较高,考虑与synchronizedList的对比
5. LinkedBlockingQueue
无界队列put()和take() 方法实现了阻塞BlockingQueue的常用方法:
poll:取数据并removepeek取数据不removeadd:添加数据,加不进去抛异常offer:添加数据,返回布尔类型
6. ArrayBlockingQueue
有界offer方法可以提供超时等待Queue和List的区别:Queue提供了offer、peek、poll、put、take等对线程友好的阻塞和等待方法
7. DelayQueue
按照等待时间排序阻塞的本质上是PriorityQueue
public class DelayQueue {
static BlockingQueue
<MyTask> tasks
= new DelayQueue<>();
static Random r
= new Random();
static class MyTask implements Delayed {
String name
;
long runningTime
;
MyTask(String name
, long rt
) {
this.name
= name
;
this.runningTime
= rt
;
}
@Override
public int compareTo(Delayed o
) {
if(this.getDelay(TimeUnit
.MILLISECONDS
) < o
.getDelay(TimeUnit
.MILLISECONDS
))
return -1;
else if(this.getDelay(TimeUnit
.MILLISECONDS
) > o
.getDelay(TimeUnit
.MILLISECONDS
))
return 1;
else
return 0;
}
@Override
public long getDelay(TimeUnit unit
) {
return unit
.convert(runningTime
- System
.currentTimeMillis(), TimeUnit
.MILLISECONDS
);
}
@Override
public String
toString() {
return name
+ " " + runningTime
;
}
}
public static void main(String
[] args
) throws InterruptedException
{
long now
= System
.currentTimeMillis();
MyTask t1
= new MyTask("t1", now
+ 1000);
MyTask t2
= new MyTask("t2", now
+ 2000);
MyTask t3
= new MyTask("t3", now
+ 1500);
MyTask t4
= new MyTask("t4", now
+ 2500);
MyTask t5
= new MyTask("t5", now
+ 500);
tasks
.put(t1
);
tasks
.put(t2
);
tasks
.put(t3
);
tasks
.put(t4
);
tasks
.put(t5
);
System
.out
.println(tasks
);
for(int i
=0; i
<5; i
++) {
System
.out
.println(tasks
.take());
}
}
}
8. SynchronousQueue
容量为0,不是用来装数据的,用来在两个线程之间传内容,类似Exchanger不能向队列里添加数据,只能用来阻塞式的put调用,即当存在消费者时,才可以put
public class SynchronusQueue {
public static void main(String
[] args
) throws InterruptedException
{
BlockingQueue
<String> strs
= new SynchronousQueue<>();
new Thread(()->{
try {
System
.out
.println(strs
.take());
} catch (InterruptedException e
) {
e
.printStackTrace();
}
}).start();
strs
.put("aaa");
System
.out
.println(strs
.size());
}
}
9. TransferQueue
可以用来做线程间传递任务,与SynchronousQueue只能传递一个任务不同的是,TransferQueue可以传递多个任务当向队列中添加任务后,会进入阻塞,直到有线程将队列中的数据取走
public class TransferQueue {
public static void main(String
[] args
) throws InterruptedException
{
LinkedTransferQueue
<String> strs
= new LinkedTransferQueue<>();
new Thread(() -> {
try {
System
.out
.println(strs
.take());
} catch (InterruptedException e
) {
e
.printStackTrace();
}
}).start();
strs
.transfer("aaa");
}
}