并发编程04_CAS

CyclicBarrier:

CyclicBarrier的字面意思是可循环使用(Cyclic )的屏障( Barrier
她的作用是使一个线程在到达屏障时被屏障阻拦进入阻塞状态,直到最后一个线程也到达屏障,这时屏障消失,所有被阻塞的的线程一起运行. 
CyclicBarrier可以用于多线程计算数据,最后合并计算结果的场景。

构造方法:

 public CyclicBarrier(int parties) 方法:

明确突破屏障需要的线程数,它其实就是下面的构造方法但是BarrierAction参数传了null值.

还有一个构造方法 public CyclicBarrier(int parties,Runnable barrierAction):

 这个构造方法是明确突破屏障需要的线程数,并且在线程碰到屏障进入阻塞状态时也能优先执行barrierAction方法.

await()方法:

每个线程调用await方法告诉CyclicBarrier我到达了屏障,然后进入阻塞状态

CountDownLatch与CyclicBarrier的区别:

  • CountDownLatch的计数器只能用一次, 而CyclicBarrier的计数器可以使用多次
  • CountDownLatch通过await()阻塞工作线程,直到所有的预备线程(初始化等)执行countDown(); 而CyclicBarrier让工作线程通过await()到达屏障自行进入阻塞,直到所有的工作线程都到达屏障进入阻塞, 再解开屏障让所有的工作线程一起运行.
  • 在多个线程同时运行上, CountDownLatch可以不限制线程数量, 而CyclicBarrier有固定的线程数量.
  • 同时, CyclicBarrier 还可以提供一个 barrierAction ,合并多线程计算结果。

Semaphore(信号量):

是用来控制同时访问特定资源的线程数量,它通过协 调各个线程,以保证合理的使用公共资源。

比如我们要从数据库中读取非常多的文件, 我们同时启用了数十个线程并发的来读取, 而数据库却只有10个接口可以提供, 这时我们需要调度这10个接口,最多同时只能有10个线程能够连接数据库,否则数据库会报错. 这时我们可以用Semaphore来做流量控制.

 

方法:

构造方法Semaphore(int permits) : 接受一个整型的数字, 表示可用的许可证数量.

acquire() :获取许可证

release(): 归还许可证

intavailablePermits():返回此信号量中当前可用的许可证数。

intgetQueueLength():返回正在等待获取许可证的线程数。

booleanhasQueuedThreads():是否有线程正在等待获取许可证。

void reducePermits( int reduction):减少 reduction 个许可证,是个 protected 方法。

Collection getQueuedThreads():返回所有等待获取许可证的线程集合,是 个 protected 方法。

Semaphore 的用法也很简单,首先线程使用 Semaphore
的 acquire()方法获取一个许可证,使用完之后调用 release()方法归还许可证。还可以用 tryAcquire()方法尝试获取许可证。

但是注意事项, 如果跳过获取许可证的过程(acquire), 直接归还许可证(relase), 相当于额外增加了许可证的数量,这是Semaphore允许的.

然而这样可能会造成异常, 我们应该尽量避免.

Exchange:

Exchanger(交换者)是一个用于线程间协作的工具类。Exchanger 用于进行 线程间的数据交换。它提供一个同步点,在这个同步点,两个线程可以交换彼此 的数据。这两个线程通过 exchange 方法交换数据,如果第一个线程先执行 exchange()方法,它会一直等待第二个线程也执行 exchange 方法,当两个线程都 到达同步点时,这两个线程就可以交换数据,将本线程生产出来的数据传递给对方。

Callable、Future 和 FutureTask

Runnable 是一个接口,在它里面只声明了一个 run()方法,由于 run()方法返 回值为 void 类型,所以在执行完任务之后无法返回任何结果。 Callable 位于 java.util.concurrent 包下,它也是一个接口,在它里面也只声明 了一个方法,只不过这个方法叫做 call(),这是一个泛型接口,call()函数返回的 类型就是传递进来的 V 类型。 Future 就是对于具体的 Runnable 或者 Callable 任务的执行结果进行取消、查 询是否完成、获取结果。必要时可以通过 get 方法获取执行结果,该方法会阻塞 直到任务返回结果。

 因为 Future 只是一个接口,所以是无法直接用来创建对象使用的,因此就 有了下面的 FutureTask。

 

FutureTask 类实现了 RunnableFuture 接口,RunnableFuture 继承了 Runnable 接口和 Future 接口,而 FutureTask 实现了 RunnableFuture 接口。所以它既可以 作为 Runnable 被线程执行,又可以作为 Future 得到 Callable 的返回值。

因此我们通过一个线程运行 Callable,但是 Thread 不支持构造方法中传递 Callable 的实例,所以我们需要通过 FutureTask 把一个 Callable 包装成 Runnable, 然后再通过这个 FutureTask 拿到 Callable 运行后的返回值。 要 new 一个 FutureTask 的实例,有两种方法 

原子操作CAS

原子操作依旧可以直接看黄猿大神的这篇博客: 老生常谈CAS

依旧是大神细致入微的分析. 这腿抱着就不想松啊.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值