【多线程与高并发】5-容器
Vector和HashTable
自带锁,现基本不用
HashMap



ConcurrentHashMap
内部用了CAS,高并发,查询效率高

ConcurrentSkipListMap
高并发并且有序(代替TreeMap,因为TreeMap用了红黑树,较为复杂,因此没有ConcurrentTreeMap)
树的结构是由concurrent+CAS
跳表结构:

CopyOnWriteArrayList
写时复制容器
多线程环境下,写时效率低(加锁),读时效率高(不加锁),适合写少读多的环境。
插入元素时,拷贝原list并扩展,最后将原list引用指向新list。
BlockingQueue
offer 加,poll 取出来并remove , peek 取出来不remove(非阻塞,都会报异常但offer除外-它有返回值)
特点:put 装,take 取 (两个都为阻塞,比如取不到一直等待,使用到了Condition,调用了await,底层用到了park,进入wait状态)
Queue对线程友好的api:offer(满了也不会抛异常,根据返回值判断)、peek、poll ,
BlockingQueue在原基础上添加了put(满了阻塞)、add(满了抛出异常)、take(没有了阻塞)
-
LinkedBlockingQueue(无界队列)
-
ArrayBlockingQueue(有界队列)
使用 ReentrantLock 和 Condition 实现一个阻塞队列 -
DelayQueue
延迟队列提供了在指定时间才能获取队列元素的功能,可用作任务调度。 -
SynchronousQueue(同步队列)
典型应用:线程池
实际上它不是一个真正的队列,因为它不会为队列中元素维护存储空间。与其他队列不同的是,它维护一组线程,这些线程在等待着把元素加入或移出队列。(轻量级)可用来在线程间安全的交换单一元素。
SynchronousQueue没有存储功能,因此put和take会一直阻塞,直到有另一个线程已经准备好参与到交付过程中。仅当有足够多的消费者,并且总是有一个消费者准备好获取交付的工作时,才适合使用同步队列。 -
TransferQueue(LinkedTransferQueue无界阻塞队列)
LinkedBolckingQueue 和 SynchronousQueue 和合体
相比较 SynchronousQueue 多了一个可以存储的队列,相比较LinkedBlockingQueue 多了直接传递元素,少了用锁来同步。性能更高,用处更大。当 put 时,如果有等待的线程,就直接将元素 “交给” 等待者, 否则直接进入队列。
典型应用:线程池
put和 transfer 方法的区别是,put 是立即返回的, transfer 是阻塞等待消费者拿到数据才返回。transfer方法和 SynchronousQueue的 put 方法类似。

eg:顾客付钱完成后,才能反馈。
- PriorityQueue
基于优先级的无界优先级队列。优先级队列的元素按照其自然顺序进行排序,或者根据构造队列时提供的 Comparator 进行排序,具体取决于所使用的构造方法。该队列不允许使用 null 元素也不允许插入不可比较的对象(没有实现Comparable接口的对象)。
内部实现-2叉树(堆排序)

案例
如何实现两个线程循环打印?thread1:A B C D thread2:1 2 3 4 结果:1A2B...
Locksupport park
public class T02_00_LockSupport {
static Thread t1 = null, t2 = null;
public static void main(String[] args) throws Exception {
char[] aI = "1234567".toCharArray();
char[] aC = "ABCDEFG".toCharArray();
t1 = new Thread(() -> {
for(char c : aI) {
System.out.print(c);
LockSupport.unpark(t2); //叫醒T2
LockSupport.park(); //T1阻塞
}
}, "t1");
t2 = new Thread(() -> {
for(char c : aC) {
LockSupport.park(); //t2阻塞
System.out.print(c);
LockSupport.unpark(t1); //叫醒t1
}
}, "t2");
t1.start();
t2.start();
}
}
CAS
public class T03_00_cas {
enum ReadyToRun {T1, T2}
static volatile ReadyToRun r = ReadyToRun.T1; //思考为什么必须volatile
public static void main(String[] args) {
char[] aI = "1234567".toCharArray();
char[] aC = "ABCDEFG".toCharArray();
new Thread(() -> {
for (char c : aI) {
while (r != ReadyToRun.T1) {}
System.out.print(c);
r = ReadyToRun.T2;
}
}, "t1").start();
new Thread(() -> {
for (char c : aC) {
while (r != ReadyToRun.T2) {}
System.out.print(c);
r = ReadyToRun.T1;
}
}, "t2").start();
}
}
ArrayBlockingQueue
public class T04_00_BlockingQueue {
static BlockingQueue<String> q1 = new ArrayBlockingQueue(1);
static BlockingQueue<String> q2 = new ArrayBlockingQueue(1);
public static void main(String[] args) throws Exception {
char[] aI = "1234567".toCharArray();
char[] aC = "ABCDEFG".toCharArray();
new Thread(() -> {
for(char c : aI) {
System.out.print(c);
try {
q1.put("ok");
q2.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "t1").start();
new Thread(() -> {
for(char c : aC) {
try {
q1.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.print(c);
try {
q2.put("ok");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "t2").start();
}
}
AtomicInteger
public class T05_00_AtomicInteger {
static AtomicInteger threadNo = new AtomicInteger(1);
public static void main(String[] args) {
char[] aI = "1234567".toCharArray();
char[] aC = "ABCDEFG".toCharArray();
new Thread(() -> {
for (char c : aI) {
while (threadNo.get() != 1) {}
System.out.print(c);
threadNo.set(2);
}
}, "t1").start();
new Thread(() -> {
for (char c : aC) {
while (threadNo.get() != 2) {}
System.out.print(c);
threadNo.set(1);
}
}, "t2").start();
}
}
sync_wait_notify
public class T07_00_sync_wait_notify {
private static volatile boolean t2Started = false;
//private static CountDownLatch latch = new C(1);
public static void main(String[] args) {
final Object o = new Object();
char[] aI = "1234567".toCharArray();
char[] aC = "ABCDEFG".toCharArray();
new Thread(()->{
//latch.await();
synchronized (o) {
while(!t2Started) {
try {
o.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(char c : aI) {
System.out.print(c);
try {
o.notify();
o.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
o.notify();
}
}, "t1").start();
new Thread(()->{
synchronized (o) {
for(char c : aC) {
System.out.print(c);
//latch.countDown()
t2Started = true;
try {
o.notify();
o.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
o.notify();
}
}, "t2").start();
}
}
lock_condition
public static void main(String[] args) {
char[] aI = "1234567".toCharArray();
char[] aC = "ABCDEFG".toCharArray();
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
new Thread(()->{
try {
lock.lock();
for(char c : aI) {
System.out.print(c);
condition.signal();
condition.await();
}
condition.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}, "t1").start();
new Thread(()->{
try {
lock.lock();
for(char c : aC) {
System.out.print(c);
condition.signal();
condition.await();
}
condition.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}, "t2").start();
}
PipedStream
public static void main(String[] args) throws Exception {
char[] aI = "1234567".toCharArray();
char[] aC = "ABCDEFG".toCharArray();
PipedInputStream input1 = new PipedInputStream();
PipedInputStream input2 = new PipedInputStream();
PipedOutputStream output1 = new PipedOutputStream();
PipedOutputStream output2 = new PipedOutputStream();
input1.connect(output2);
input2.connect(output1);
String msg = "Your Turn";
new Thread(() -> {
byte[] buffer = new byte[9];
try {
for(char c : aI) {
input1.read(buffer);
if(new String(buffer).equals(msg)) {
System.out.print(c);
}
output1.write(msg.getBytes());
}
} catch (IOException e) {
e.printStackTrace();
}
}, "t1").start();
new Thread(() -> {
byte[] buffer = new byte[9];
try {
for(char c : aC) {
System.out.print(c);
output2.write(msg.getBytes());
input2.read(buffer);
if(new String(buffer).equals(msg)) {
continue;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}, "t2").start();
}
Exchanger
public class T12_00_Exchanger_Not_Work {
private static Exchanger<String> exchanger = new Exchanger<>();
public static void main(String[] args) {
char[] aI = "1234567".toCharArray();
char[] aC = "ABCDEFG".toCharArray();
new Thread(()->{
for(int i=0; i<aI.length; i++) {
System.out.print(aI[i]);
try {
exchanger.exchange("T1");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
new Thread(()->{
for(int i=0; i<aC.length; i++) {
try {
exchanger.exchange("T2");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.print(aC[i]);
}
}).start();
}
}
TransferQueue
public static void main(String[] args) {
char[] aI = "1234567".toCharArray();
char[] aC = "ABCDEFG".toCharArray();
TransferQueue<Character> queue = new LinkedTransferQueue<Character>();
new Thread(()->{
try {
for (char c : aI) {
System.out.print(queue.take());
queue.transfer(c);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "t1").start();
new Thread(()->{
try {
for (char c : aC) {
queue.transfer(c);
System.out.print(queue.take());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "t2").start();
}

浙公网安备 33010602011771号