并发容器

##并发容器练习###############################################
练习1:
启动若干线程,并行访问同一个容器中的数据。保证获取容器中数据时没有数据错误,且线程安全。
如:售票,秒杀等业务。

##并发容器大纲###############################################
1.ConcurrentHashMap
2.ConcurrentSkipListMap
3.CopyOnWriteArrayList
4.ConcurrentLinkedQueue
5.LinkedBlockingQueue
6.ArrayBlockingQueue
7.DelayQueue
8.LinkedTransferQueue
9.SynchronusQueue

##并发容器详细###############################################
1.ConcurrentHashMap和ConcurrentSkipListMap。
①ConcurrentHashMap:
效率高,线程安全。量级较synchronized低。key和value不能为null。
②ConcurrentSkipListMap:
底层跳表实现同步。有序,效率比ConcurrentHashMap稍低。
③代码实现:
public class Test_01_ConcurrentMap {
public static void main(String[] args) {
final Map<String, String> map = new ConcurrentHashMap<>();
final Map<String, String> map = new ConcurrentSkipListMap<>();
final Random r = new Random();
Thread[] array = new Thread[100];
final CountDownLatch latch = new CountDownLatch(array.length); //门闩
long begin = System.currentTimeMillis();
for(int i = 0; i < array.length; i++){
array[i] = new Thread(new Runnable() {
public void run() {
for(int j = 0; j < 10000; j++){map.put(“k”+r.nextInt(100000), “v”+r.nextInt(100000));}
latch.countDown();
}
});
}
for(Thread t : array){t.start();}
try {latch.await();}
catch (InterruptedException e) {e.printStackTrace();}
long end = System.currentTimeMillis();
System.out.println("执行时间为 : " + (end-begin) + “毫秒!”);
}
}

2.CopyOnWriteArrayList
①CopOnWriteArrayList:
写时复制集合。写入效率低,读取效率高。每次写入数据,都会创建一个新的底层数组。
②代码实现:
public class Test_02_CopyOnWriteList {
public static void main(String[] args) {
final List list = new CopyOnWriteArrayList<>();
final Random r = new Random();
Thread[] array = new Thread[100];
final CountDownLatch latch = new CountDownLatch(array.length);
long begin = System.currentTimeMillis();
for(int i = 0; i < array.length; i++){
array[i] = new Thread(new Runnable() {
public void run() {
for(int j = 0; j < 1000; j++){list.add(“value” + r.nextInt(100000));}
latch.countDown();
}
});
}
for(Thread t : array){t.start();}
try {latch.await();}
catch (InterruptedException e) {e.printStackTrace();}
long end = System.currentTimeMillis();
System.out.println("执行时间为 : " + (end-begin) + “毫秒!”);
System.out.println("List.size() : " + list.size());
}
}

3.ConcurrentLinkedQueue
①ConcurrentLinkQueue:
基础链表同步队列.
peek() -> 查看queue中的首数据
poll() -> 获取queue中的首数据

②代码实现:
public class Test_03_ConcurrentLinkedQueue {
public static void main(String[] args) {
Queue queue = new ConcurrentLinkedQueue<>();
for(int i = 0; i < 10; i++){queue.offer(“value” + i);}
System.out.println(queue);
System.out.println(queue.size());
// peek() -> 查看queue中的首数据
System.out.println(queue.peek());
System.out.println(queue.size());
// poll() -> 获取queue中的首数据
System.out.println(queue.poll());
System.out.println(queue.size());
}
}

4.LinkedBlockingQueue
①LinkedBlockingQueue:【无界阻塞容器】
put自动阻塞,队列容量满后,自动阻塞。
take自动阻塞,队列容器为0,自动阻塞。
默认的容量为Integer.MAX_VALUE,添加速度大于删除速度时候,可能会内存溢出,所以要指定容量大小。

②代码实现:
public class Test_04_LinkedBlockingQueue {
final BlockingQueue queue = new LinkedBlockingQueue<>(10);
final Random r = new Random();
public static void main(String[] args) {
final Test_04_LinkedBlockingQueue t = new Test_04_LinkedBlockingQueue();
//生产者线程
new Thread(new Runnable() {
public void run() {
while(true){
try {
t.queue.put(“value”+t.r.nextInt(1000));
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {e.printStackTrace();}
}
}}, “producer”).start();
//消费者线程
for(int i = 0; i < 10; i++){
new Thread(new Runnable() {
public void run() {
while(true){
try {System.out.println(Thread.currentThread().getName()+"-"+t.queue.take());}
catch (InterruptedException e) {e.printStackTrace();}
}
}}, “consumer”+i).start();
}
}
}

5.ArrayBlockingQueue
①ArrayBlockingQueue:【有界容器】
(a).put方法是放入内容,在容量不足的时候,阻塞等待。
(b).add方法是放入内容,在容量不足的时候,抛出异常。
©.offer方法放入内容,
单参数offer方法,不阻塞。容量不足的时候,返回false。当前新增数据操作放弃。
参数offer方法offer(value,times,timeunit),容量不足的时候,阻塞times时长。
如果在阻塞时长内,容量空闲,新增数据返回true。如果阻塞时长范围内,无容量空闲,放弃新增数据,返回false。

②实现代码:
public class Test_05_ArrayBlockingQueue {
final BlockingQueue queue = new ArrayBlockingQueue<>(3);
public static void main(String[] args) {
final Test_05_ArrayBlockingQueue t = new Test_05_ArrayBlockingQueue();
for(int i = 0; i < 5; i++){
System.out.println("add method : " + t.queue.add(“value”+i));
try {
t.queue.put(“put”+i);
} catch (InterruptedException e) {e.printStackTrace();}
System.out.println(“offer:”+t.queue.offer(“value”+i));
try {
System.out.println(“offer:”+t.queue.offer(“value”+i,1,TimeUnit.SECONDS));
} catch (InterruptedException e) {e.printStackTrace();}
}
System.out.println(t.queue);
}
}

6.DelayQueue
①DelayQueue:【有界容器】
延迟队列提供了在指定时间才能获取队列元素的功能。
根据比较机制,实现自定义处理顺序的队列。
延时队列不能存放空元素。
常用于定时任务。

②实现代码:
public class Test_06_DelayQueue {
static BlockingQueue<MyTask_06> queue = new DelayQueue<>();
public static void main(String[] args) throws InterruptedException {
long value = System.currentTimeMillis(); //指定一个时间
MyTask_06 task1 = new MyTask_06(value + 2000);
MyTask_06 task2 = new MyTask_06(value + 1000);
MyTask_06 task3 = new MyTask_06(value + 9000);
queue.put(task1);
queue.put(task2);
queue.put(task3);
System.out.println(value);
for(int i = 0; i < 5; i++){
MyTask_06 mtask = queue.take();
String str = mtask.toString();
System.out.println(str);
}
}
}
//类功能:根据时间大小执行具体的任务类
class MyTask_06 implements Delayed {
private long compareValue;
public MyTask_06(long compareValue){this.compareValue = compareValue;}
/**
* 比较大小。自动实现升序
* 建议和getDelay方法配合完成。
* 如果在DelayQueue是需要按时间完成的计划任务,必须配合getDelay方法完成。
/
@Override
public int compareTo(Delayed o) {
return (int)(this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS));
}
/
*
* 获取计划时长的方法。
* 根据参数TimeUnit来决定,如何返回结果值。
*/
@Override
public long getDelay(TimeUnit unit) {
return unit.convert(compareValue - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}
public String toString(){return "Task compare value is : " + this.compareValue;}
}

7.LinkedTransferQueue
①LinkedTransferQueue:【转移队列】
转移队列。
add->队列会保存数据,不做阻塞等待。
transfer-> 是TransferQueue的特方法。必须消费者take()方法的调用者。
如果没任意线程消费数据,transfer方法阻塞。
用于处理即时消息。

②实现代码:
public class Test_07_TransferQueue {
TransferQueue queue = new LinkedTransferQueue<>();
public static void main(String[] args) {
final Test_07_TransferQueue t = new Test_07_TransferQueue();
//线程执行生产者(take())
new Thread(new Runnable() {
public void run() {
try {
//t.queue.add(“test string”);
t.queue.transfer(“test string”); //执行步骤3:t.queue.transfer(“xxx”)
System.out.println(“add ok”);
} catch (Exception e) {e.printStackTrace();}
}}).start();
//休眠2秒
try {TimeUnit.SECONDS.sleep(2);}
catch (InterruptedException e) {e.printStackTrace();}
//线程执行消费者(take())
new Thread(new Runnable() {
public void run() {
try {
System.out.println(Thread.currentThread().getName() + " thread begin " );//执行步骤1
String str = t.queue.take();//执行步骤2:t.queue.take()
System.out.println(Thread.currentThread().getName() + “-” + str);
} catch (InterruptedException e) {e.printStackTrace();}
}}, “output thread”).start();
}
}

8.SynchronusQueue
①SynchronusQueue:【同步队列】
同步队列,是一个容量为0的队列。是一个特殊的TransferQueue。必须现有消费线程等待,才能使用的队列。
add方法,无阻塞。若没消费线程阻塞等待数据,则抛出异常。
put方法,阻塞。若没消费线程阻塞等待数据,则阻塞。

②实现代码:
public class Test_08_SynchronusQueue {
BlockingQueue queue = new SynchronousQueue<>();
public static void main(String[] args) {
final Test_08_SynchronusQueue t = new Test_08_SynchronusQueue();
//线程模拟等待2秒后在进行take()消费
new Thread(new Runnable() {
public void run() {
try {
System.out.println(Thread.currentThread().getName() + " thread begin " );
try {TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {e.printStackTrace();}
String str = t.queue.take();
System.out.println(Thread.currentThread().getName()+str);
} catch (InterruptedException e) {e.printStackTrace();}
}}, “消费者:”).start();

	//生产者放入数据:put("xxxx")、add(xxx)
	t.queue.add("test add");
	try {t.queue.put("test put");
	} catch (InterruptedException e) {e.printStackTrace();}
	System.out.println(Thread.currentThread().getName() + "queue size :" + t.queue.size());
}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

java之书

会持续更新实用好的文章谢谢关注

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值