并发容器

本文探讨了多种并发容器的性能特点,包括ConcurrentHashMap、ConcurrentSkipListMap、Hashtable、HashMap等,并通过执行时间对比展示了它们在多线程环境下的表现。重点介绍了ConcurrentHashMap的高并发优势和CopyOnWrite容器在写少读多场景的适用性。还讨论了不同类型的队列,如ConcurrentLinkedQueue、LinkedBlockingQueue、ArrayBlockingQueue、DelayQueue、TransferQueue和SynchronousQueue,分析了它们各自的应用场景,如定时任务、实时系统消息同步等。

1.  ConcurrentHashMap

* 本方法测试点(基于jdk1.8):
 *   ConcurrentHashMap
 *   ConcurrentSkipListMap
 *   Hashtable
 *   HashMap
 *   执行时间对比,Map<String,String> 而Set<String>同理

 * 理解:
 *   SkipList跳表
 *   用CountDownLatch统计多线程执行

package container_test;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.CountDownLatch;

/**
 * 
 * 本方法测试点(基于jdk1.8):
 *   ConcurrentHashMap
 *   ConcurrentSkipListMap
 *   Hashtable
 *   HashMap
  *      执行时间对比
 *   Map<String,String> 而Set<String>同理
 * 
 * 理解:
 *   SkipList跳表
  *        用CountDownLatch统计多线程执行时间
 *  
 * @author x1c
 */
public class ConcurrentMapTest {
	public static void main(String[] args) {
//		Map<String, String> map = new ConcurrentHashMap<>(); //多线程执行总时间:76ms 94ms 141ms 203ms 188ms 94ms 79ms
		//高并发并且排序
//		Map<String, String> map = new ConcurrentSkipListMap<>(); //多线程执行总时间:78ms 79ms 188ms 437ms 79ms 266ms 70ms 
		
		//HashTable默认实现都带锁 效率较低
//		Map<String, String> map = new Hashtable<>(); //多线程执行总时间:117ms 141ms 79ms 78ms 78ms 78ms 125ms
		Map<String, String> map = new HashMap<>(); //多线程执行总时间:109ms 94ms 110ms 79ms 79ms 78ms 78ms
		//Collections.synchronizedMap(map);
		//treeMap
		
		Random random = new Random();
		Thread[] threads = new Thread[100]; //100个线程
		/**
		 * Constructs a {@code CountDownLatch} initialized with the given count.
		 * count the number of times {@link #countDown} must be invoked
		 * before threads can pass through {@link #await}
		 */
		CountDownLatch latch = new CountDownLatch(threads.length); 
		long start = System.currentTimeMillis();
		for (int i = 0; i < threads.length; i++) {
			threads[i] = new Thread(()->{
				for (int j = 0; j < 100000; j++) {
					map.put("key"+random.nextInt(100000), "b"+random.nextInt(100000));
					latch.countDown(); //sync.releaseShared(1);
				}
			}
			);
		}
		
		Arrays.asList(threads).forEach(tt->tt.start()); //依次启动线程
		
		try {
			/**
			 * Causes the current thread to wait until the latch has counted down to
			 * zero, unless the thread is {@linkplain Thread#interrupt interrupted}.
			 */
			latch.await();//门闩为0 唤醒
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		long end = System.currentTimeMillis();
		
		System.err.println("多线程执行总时间:"+(end -start)+"ms");
		
	}
}

CountHashMap 分段锁  16段

 private static final int DEFAULT_CAPACITY = 16;

多线程执行ConcurrentHashMap总体较高!线程安全!

2.CopyOnWrite

 * 写时复制容器 CopyOnWrite
 * 多线程环境下,写时效率低,读时效率高
 * 适合写少读多的环境
 * 实际使用场合:如事件监听器

package container_test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.Vector;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * 写时复制容器 CopyOnWrite
 * 多线程环境下,写时效率低,读时效率高
 * 适合写少读多的环境
 * 实际使用场合:如事件监听器
 * @author x1c
 *
 */
public class CopyOnWriteList {
	public static void main(String[] args) {
		//ArrayList会有并发问题
		List<String> lists = new ArrayList<>(); //private static final int DEFAULT_CAPACITY = 10;
//		List<String> lists = new Vector<>(); //this(10);
//		List<String> lists = new CopyOnWriteArrayList<>(); 
		
		Random random = new Random();
		Thread[] threads = new Thread[100];
		
		for (int i = 0; i < threads.length; i++) {
			Runnable task = new Runnable() {
				
				@Override
				public void run() {
					for (int j = 0; j < 1000; j++) {
						lists.add("a"+random.nextInt(1000));
					}
				}
			};
			threads[i] = new Thread(task);
		}
		
		runAndComputeTime(threads); //计算各个线程执行总时间
		
		System.out.println("list.size:"+lists.size());
		
	}
	
	static void runAndComputeTime(Thread[] threads) {
		long start = System.currentTimeMillis();
		Arrays.asList(threads).forEach(tt->tt.start()); //各个线程启动
		Arrays.asList(threads).forEach(tt->{
			try {
				tt.join(); //Waits for this thread to die.
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		);
		long end = System.currentTimeMillis();
		System.err.println("线程执行总时间:"+(end - start)+"ms");
	}
}

/**
 * 测试结果:
 * 	CopyOnWriteList
 * 		线程执行总时间:4626ms
		list.size:100000
	Vector(加了锁)
		线程执行总时间:169ms
		list.size:100000
	ArrayList
		线程执行总时间:138ms
		list.size:97588

*/

3. SynchronizedList

list实现加锁

package container_test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
 * list实现加锁
 * 
 * @author x1c
 *
 */
public class SynchronizedList {
	public static void main(String[] args) {
		List<String> list = new ArrayList<>();
		List<String> synchronizedList = Collections.synchronizedList(list); //已经加锁
	}
}

4.ConcurrentLinkedQueue

无界队列

package container_test;

import java.util.Deque;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * ConcurrentQueue
 *  重要且经常用!
 *  游戏消息同步:queue+threadPool
 * 
 * @author x1c
 *
 */
public class ConcurrentQueue {
	public static void main(String[] args) {
		Queue<String> strs = new ConcurrentLinkedQueue<>(); //ConcurrentLinkedQueue 无界队列
		
		for (int i = 0; i < 10; i++) {
//			boolean java.util.Queue.offer(String e)
			strs.offer("a"+i); //offer  
		}
		
		System.out.println(strs);
		System.out.println(strs.size());
		
		/**
		 * Retrieves and removes the head of this queue,
		 * or returns {@code null} if this queue is empty.
		 */
		System.out.println(strs.poll()); //拿出使用并删除
		System.out.println(strs.size());
		
		System.out.println(strs.peek()); //拿出使用而不删除
		System.out.println(strs.size());
		
		//双端队列Deque  详见javaAPI
//		Deque<E>
	}
}

5.LinkedBlockingQueue

 * LinkedBlockingQueue
 *   阻塞式无界队列

package container_test;

import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * LinkedBlockingQueue
  *   阻塞式无界队列
 * @author x1c
 *
 */
public class T05_LinkedBlockingQueue {
	static BlockingQueue<String> strs = new LinkedBlockingQueue<>(); //阻塞式无界队列
	
	static Random random = new Random();
	
	public static void main(String[] args) {
		//生产者
		new Thread(()->{
			for (int i = 0; i < 10; i++) {
				try {
					strs.put("a"+random.nextInt(1000)); //如果满了,就会等待
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				try {
					TimeUnit.MILLISECONDS.sleep(random.nextInt(1000)); //如果空了,就会等待
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
		,"p1").start();
		
		//消费者
		for (int i = 0; i < 10; i++) {
			new Thread(()->{
				try {
					System.out.println(Thread.currentThread().getName()+"--take--" + strs.take());
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			).start();
		}
	}
}

6.ArrayBlockingQueue

 * ArrayBlockingQueue
 *   阻塞式有界队列

package container_test;

import java.util.Random;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * ArrayBlockingQueue
  *   阻塞式有界队列
 * @author x1c
 *
 */
public class T05_ArrayBlockingQueue {
	static BlockingQueue<String> strs = new ArrayBlockingQueue<>(10); //阻塞式有界队列
	
	public static void main(String[] args) {
		for (int i = 0; i < 10; i++) {
			strs.add("a"+i);
		}
		
		try {
			strs.put("111111"); //阻塞
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
//		strs.offer("111111"); //false
//		try {
//			strs.offer("1111111", 1000, TimeUnit.MICROSECONDS); //false
//		} catch (InterruptedException e) {
//			e.printStackTrace();
//		}
		
//		strs.add("111111");
		System.out.println(strs);
	}
}

7.DelayQueue

 * DelayQueue
  * 无界队列
  * 插入有序 等待时间最长的元素先被消费
 * 场景:定时任务

package container_test;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

/**
 * DelayQueue
  * 无界队列
  * 插入有序 等待时间最长的元素先被消费
 * 
 * 场景:定时任务
 *   
 * @author x1c
 *
 */
public class T07_DelayQueue {
	static BlockingQueue<Mytask> tasks = new DelayQueue<>(); //DelayQueue 元素要实现Delayed接口
	
	//interface Delayed extends Comparable
	//DelayQueue<E extends Delayed> extends AbstractQueue<E>
	static class Mytask implements Delayed{ 
		long runingTime;

		public Mytask(long runingTime) {
			this.runingTime = runingTime;
		}

		@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(runingTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
		}

		@Override
		public String toString() {
			return "Mytask [runingTime=" + runingTime + "]";
		}
		
	}
	
	public static void main(String[] args) throws InterruptedException {
		long now = System.currentTimeMillis();
		Mytask t1 = new Mytask(now + 1000);
		Mytask t2 = new Mytask(now + 2000);
		Mytask t3 = new Mytask(now + 3000);
		Mytask t4 = new Mytask(now + 4000);
		Mytask t5 = new Mytask(now + 50);
		
		tasks.put(t1); //DelayQueue<E extends Delayed> extends AbstractQueue<E>
		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.TransferQueue

 * TransferQueue
 * 不放入队列,直接给消费者线程,若无消费者阻塞
 * 场景:实时系统消息同步,提高并发 如netty框架用的比较多

package container_test;

import java.util.concurrent.LinkedTransferQueue;

/**
 * TransferQueue
 *   不放入队列,直接给消费者线程,若无消费者阻塞
 * 
 * 场景:实时系统消息同步,提高并发 如netty框架用的比较多
 *   
 * @author x1c
 *
 */
public class T08_TransferQueue {
	public static void main(String[] args) {
		LinkedTransferQueue<String> strs = new LinkedTransferQueue(); //LinkedTransferQueue

		//消费者线程 先
		new Thread(()->{
				try {
					System.out.println(strs.take());
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
		}
		).start();
		
		try {
			strs.transfer("111");
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		}
		
		//消费者线程
//		new Thread(()->{
//				try {
//					System.out.println(strs.take());
//				} catch (InterruptedException e) {
//					e.printStackTrace();
//				}
//		}
//		).start();
	}
	
	
	
}

9.SynchronousQueue

 * SynchronousQueue
 * 同步队列
 * 容量为0

package container_test;

import java.util.concurrent.LinkedTransferQueue;
import java.util.concurrent.SynchronousQueue;

/**
 * SynchronousQueue
 * 同步队列
 * 容量为0
 *   
 * @author x1c
 *
 */
public class T09_SynchronousQueue {
	public static void main(String[] args) {
		SynchronousQueue<String> strs = new SynchronousQueue(); //LinkedTransferQueue

		//消费者线程 先
		new Thread(()->{
				try {
					System.out.println(strs.take());
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
		}
		).start();
		
		try {
			strs.put("111"); //阻塞等待消费者消费
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(strs.size());
	}
	
	
	
}

小结:

---------------------------------------------------------------------------

1.Map/Set

       HashMap

       TreeMap    (SortMap接口,基于红黑树,默认按键的升序排序 )

       LinkedHashMap

       并发较小:

       Hashtable

       Collections.synchronizedXXX

       高并发:

       ConcurrentHashMap

       ConcurrentSkipList  跳表  有序

----------------------------------------------------------------------------

2. List

    不同步:

          ArrayList

          LinkedList

    同步:

          Vector

          Collections.synchronizedXXX

  CopyOnWriteList 写时复制,写少读多时效率高  不需要加锁 因为不存在脏读可能

--------------------------------------------------------------------------------

3. Queue

       ConcurrentLinkedQueue  高并发

       BlockingQueue 阻塞式队列

              LinkedBlockingQueue  无界队列

             ArrayBlockingQueue  有界队列

             TransferQueue  直接给消费者线程 否则阻塞

             SynchronousQueue  特殊的TransferQueue 容量为0

      DelayQueue 执行定时任务

--------------------------------------------------------------------------------------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值