欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

并发容器

程序员文章站 2022-07-13 08:58:54
...

exchanher交换数据,代码如下:

package concurrent;
import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.*;
public class ExchangerDemo {
	
	public static void main(String[] args) {
        ExecutorService executor = Executors.newCachedThreadPool();
        
        final Exchanger exchanger = new Exchanger();
        executor.execute(new Runnable() {
            String data1 = "克拉克森,小拉里南斯";
            
 
            @Override
            public void run() {
                nbaTrade(data1, exchanger);
            }
        });
        
 
        executor.execute(new Runnable() {
            String data1 = "格里芬";
 
            @Override
            public void run() {
                nbaTrade(data1, exchanger);
            }
        });
        
        executor.execute(new Runnable() {
            String data1 = "哈里斯";
 
            @Override
            public void run() {
                nbaTrade(data1, exchanger);
            }
        });
        
        executor.execute(new Runnable() {
            String data1 = "以赛亚托马斯,弗莱";
 
            @Override
            public void run() {
                nbaTrade(data1, exchanger);
            }
        });
        
        executor.shutdown();
    }
 
    private static void nbaTrade(String data1, Exchanger exchanger) {
        try {
            System.out.println(Thread.currentThread().getName() + "在交易截止之前把 " + data1 + " 交易出去");
            Thread.sleep((long) (Math.random() * 1000));
 
            String data2 = (String) exchanger.exchange(data1);
            System.out.println(Thread.currentThread().getName() + "交易得到" + data2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

运行得到结果如下,从结果可以看出来,data1和data2得到了交换


pool-1-thread-1在交易截止之前把 克拉克森,小拉里南斯 交易出去
pool-1-thread-2在交易截止之前把 格里芬 交易出去
pool-1-thread-3在交易截止之前把 哈里斯 交易出去
pool-1-thread-4在交易截止之前把 以赛亚托马斯,弗莱 交易出去
pool-1-thread-2交易得到哈里斯
pool-1-thread-3交易得到格里芬
pool-1-thread-4交易得到克拉克森,小拉里南斯
pool-1-thread-1交易得到以赛亚托马斯,弗莱

对于增删操作用得上List或者Set。都是针对整个容器,每次操作都不可避免地需要锁住整个容器空间,这样性能大打折扣,实现线程安全的List/Set只要修改操作的时候进行同步,比如java.util.Collections.synchronizedList(List)或者java.util.Collections.synchronizedSet(Set),当然也可以用Lock来实现List/Set。但这种情况下是多读少写,如果能实现更优秀的算法,ReadWriteLock,CopyOnWriteArrayList/CopyOnWriteArraySet都是思路,后两者最大的好处就是"读“不用锁。思路是改的时候复制一份新的List/Set,在新的上修改,然后复制给旧的,写操作要加锁。可以点击下面链接看看源码。
ArrayList和CopyOnWriteArrayList

上面链接可以看出CopyOnWriteArrayList有几个要点

  1. 实现了List接口
  2. 内部持有一个ReentrantLock lock = new ReentrantLock();
  3. 底层是用volatile transient声明的数组 array
  4. 读写分离,写时复制出一个新的数组,完成插入、修改或者移除操作后将新数组赋值给array

增删改的时候,都会创建一个新的数组,改的过程中,get可按照原来的数组进行查看。如果在增删改中直接修改原来的数组,可能会造成执行程序读操作获取不到数据。支持读多少写的并发情况。

相关标签: 技术总结