并发编程-集合
普通的集合
List\Set\Map,并发的环境下,遍历的过程中不容许更新操作(增删改)
import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class CollectionDemo { public static void main(String[] args) { List<User> list=new ArrayList<>(); for (int i = 0; i < 20; i++) { User user = new User(i, "User" + i); list.add(user); } //java.util.ConcurrentModificationException // Iterator<User> it=list.iterator(); // while(it.hasNext()){ // User user=it.next(); // if("User6".equals(user.getName())) // list.remove(user); // } for (int i = 0; i < 20; i++){ if(i % 2 == 0){ User user = (User)list.get(i); // 每次删除元素,后面的都会向前移动一个位置,3变成2,混乱了 list.remove(user); } } System.err.println(list); } }
并发集合
非阻塞式集合(Non-Blocking Collection) ConcurrentLinkedDeque
这类集合也包括添加和移除数据的方法。如果方法不能立即被执行,则返回null或抛出异常,但是调用这个方法的线程不会被阻塞。
实例
添加大量的数据到一个列表中;
从同一个列表中移除大量的数据。
import java.util.concurrent.ConcurrentLinkedDeque; public class CollectionDemo01 { public static void main(String[] args) throws InterruptedException{ ConcurrentLinkedDeque<String> list=new ConcurrentLinkedDeque(); //添加数据 Thread[] add=new Thread[100]; for (int i = 0; i < 100; i++) { add[i]=new Thread(()->{ for (int j = 0; j < 10000; j++) { list.add(Thread.currentThread().getName()+":Element "+j); } }); add[i].start(); add[i].join(); } System.out.println("after add size:"+list.size()); //移除数据 Thread[] poll=new Thread[100]; for (int i = 0; i < 100; i++) { poll[i]=new Thread(()->{ for (int j = 0; j < 5000; j++) { list.pollLast(); list.pollFirst(); } }); poll[i].start(); poll[i].join(); } System.out.println("after poll size:"+list.size()); } }
阻塞式集合(Blocking Collection) LinkedBlockingDeque
阻塞式集合(Blocking Collection):这类集合包括添加和移除数据的方法。当集合已满或为空时,被调用的添加或者移除方法就不能立即被执行,那么调用这个方法的线程将被阻塞,一直到该方法可以被成功执行。
import java.util.Date; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.TimeUnit; public class BlockDequeDemo { public static void main(String[] args) { LinkedBlockingDeque<String> list=new LinkedBlockingDeque(3); Thread thread=new Thread(()->{ for (int i = 0; i < 3; i++) { for (int j = 0; j < 5; j++) { String str=new String(i+":"+j); try { list.put(str.toString()); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("client:"+str+(new Date())); } } }); thread.start(); for (int i = 0; i < 5; i++) { for (int j = 0; j < 3; j++) { try { String str=list.take(); System.out.println("main:take "+str+" size:"+list.size()); } catch (InterruptedException e) { e.printStackTrace(); } try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); } } } System.out.println("end"); } }
import com.sun.javafx.animation.TickCalculation; import java.util.Random; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; public class CarDemo { public static void main(String[] args) { //创建Semaphore Semaphore sp=new Semaphore(5); Thread[] car=new Thread[10]; for (int i = 0; i < 10; i++) { car[i]=new Thread(()->{ //请求许可 try { sp.acquire(); System.out.println(Thread.currentThread().getName()+"可以进停车场"); } catch (InterruptedException e) { e.printStackTrace(); } //使用资源 try { int val= new Random().nextInt(10); TimeUnit.SECONDS.sleep(val); System.out.println(Thread.currentThread().getName()+"停留了"+val+"秒"); } catch (InterruptedException e) { e.printStackTrace(); } //离开(释放资源) try { sp.release(); System.out.println(Thread.currentThread().getName()+"离开停车场"); } catch (Exception e) { e.printStackTrace(); } },"car["+i+"]"); car[i].start(); } } }
ArrayBlockingQueue
ConcurrentHashMap
ConcurrentLinkedQueue
ConcurrentSkipListMap
ConcurrentSkipListSet
CopyOnWriteArrayList
CopyOnWriteArraySet