• java.util.concurrent概述


    简称juc,是一个在并发编程中有用的包,有5部分内容:

    1.atomic

    原子类的包,在源码里,atomic自己就是一个包,支持对单个变量进行无锁线程的安全编辑, 如AtomicInteger,修饰单个变量,可以实现int类型原子的加;本质上,它扩展了volatile的概念并且提供了一个方法:

                                                                   boolean compareAndSet(expectedValue,  updateValue);

    这个方法底层用CAS实现,这个方法参数expectedValue是一个旧的预期值,updateValue是更新后的新值,如果内存中的值和expectedValue相等,就把内存中的值更新为updateValue,然后返回true,否则不更新内存的值,返回false;这是一个比较和交换的过程,为什么它是原子性的呢?因为硬件指令集的发展,比较并交换(Compare-And-Swap)在语义上看起来需要多次操作的行为,但是只需要通过一条处理器指令就可以完成,所以他是原子性的,这类指令还有:

    • 测试并设置(Test-And-Set)
    • 获取并增加(Fetch-And-Increment)
    • 交换(Swap) 
    • 加载链接/条件存储(Load-Linked/Store-Conditional,LL/SC)

    原子性的访问和更新遵循volatile原则:

    • get 获得volatile修饰的变量的内存值
    • set 赋值volatile修饰的变量的内存值
    • lazySet 最终赋值,不能防止重排序;
    • weakCompareAndSet 原子性的读和有条件的写,与compareAndSet的底层实现相同;

    除了修饰单个变量外,还能提供了以Updater命名的类,这些类可以对任何类的任何volatile修饰的字段做compareAndSet操作,AtomicReferenceFieldUpdater,AtomicIntegerFieldUpdater和AtomicIntegerFieldUpdater提供对相关字段类型的访问,是基于反射的原理实现的,可以原子性的操作各个字段;

    还提供可对数组元素的原子操作,AtomicIntegerArray,AtomicLongArray,AtomicReferenceArray,这些类为数组元素提供了volatile的语义;

    AtomicMarkableReference可以把布尔类型和一个引用类型关联起来,例如表示引用的对象在逻辑上已经被删除,或者做版本号的更新;

    2.locks

    提供接口和类为了不同条件的locking和waiting,与内置的synchronization和monitors不同;

    lock接口支持不同的锁的规则(可重入锁,公平锁等等),并且可以被使用在没有阻塞结构的环境中,包括hand-over-hand和锁重新排序算法,实现类为ReentrantLock;

    ReadWriteLock接口支持读共享,写独占的锁,实现类ReentrantReadWriteLock;

    Condition接口描述可能与锁关联的条件变量,类似于使用Object.wait()访问隐式监视器,但是需要扩展功能;特别的,多个Condition可以对应一个Lock,为了避免兼容性问题,所以Condition方法的名字是不同的;

    AbstractQueuedSynchronizer作为一个有用的超类,用于定义锁和其他依赖于阻塞队列的同步器;AbstractQueueLoneSynchronizer提供可相同的方法,但是扩展了对64位同步状态的支持;他们都扩展了AbstractOwnableSynchronizer类,它是一个简单的类,帮助记录当前持有独占锁的线程;LockSupport提供了低级的阻塞和解除阻塞的支持;

    3.collections

    提供支持并发的queue,deque,map的集合接口,以及具体阻塞队列的实现类;使用reentrantLock进行加锁,保证并发的安全性;CopyOnWriteArrayList和CopyOnWriteArrayList所有可变操作(添加,设置和删除)都会创建新的副本数组,迭代器不会抛出ConcurrentModificationException异常;遵循内存一致性的影响,所有写操作happen-before后来的访问和删除操作;

    4.executor

    Executor接口支持提交Runnable任务,把任务提交从任务运行机制中解耦出来,包括线程使用细节和调度细节等;一般使用Executor取代明显的线程创建,例如:new Thread(new  (RunnableTask())).start()你可以写成Executor executor = anExecutor; executor.executor(new  (RunnableTask());

    ExecutorService接口能拒绝新的任务执行,提供了shutdown()和shutdownNow()方法;shotdown()方法终止之前允许之前提交的任务执行,而shotdownNow防止等待的任务启动并且尝试停止正在执行的任务;终止时,没有任务在执行,没有任务在等待,没有任务被提交;所有没有使用的ExecutorService都应该关闭,允许回收其资源;

    ThreadPoolExecutor是线程池,它解决了两个问题:1、在执行大量任务时,由于减少了每个任务的调用开销,有了更高的性能;2、它们提供了一种绑定和管理资源(包括线程)的方法,这些资源在执行一组任务时使用。每个ThreadPoolExecutor还维护一些基本的统计信息,例如完成任务的数量。

    Callable返回结果并可能抛出异常的任务,定义一个没有调用参数的方法call()

    Future表示异步计算的结果方法用于检查计算是否完成,等待其完成,并检索计算结果。只有当计算完成时,才能使用方法get检索结果,必要时阻塞,直到准备好为止。取消由cancel方法执行。还提供了其他方法来确定任务是否正常完成或取消。一旦计算完成,就不能取消计算。如果为了可取消性而希望使用Future,但不提供可用的结果,则可以声明表单Future<?>并返回null作为优先任务的结果。

    Delayed一种混合样式的接口,用于标记在给定延迟之后应该处理的对象。该接口的实现必须定义一个compareTo方法,该方法提供与其getDelay方法一致的排序。

    5.tools

    CountDownLatch一种同步辅助,允许一个或多个线程等待直到其他线程完成;使用给定的计数初始化CountDownLatch。某个线程调用await()方法会阻塞,直到其他线程调用countDown()方法使当前计数变为0为止,在此之后,所有的等待线程都被释放;计数无法重置;

    CyclicBarrier一种同步辅助,允许一组线程相互等待,直到达到相同的屏障点;

    Exchanger一个同步点,在这个同步点上,线程可以对成对的元素进行配对和交换;

  • 相关阅读:
    计算器第七次作业——总结
    计算器第六次作业——界面
    链表反转
    计算器第五次作业——更新
    求圆的面积
    计算器第四次作业——实现
    计算器第三次作业——完善
    计算器第三次作业——初步
    成长函数
    单个H扩展到多个H时,机器学习的保证
  • 原文地址:https://www.cnblogs.com/smailjunk/p/10132348.html
Copyright © 2020-2023  润新知