多线程工具类:CountDownLatchCyclicBarrierSemaphoreLockSupport

Posted Java学习录

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程工具类:CountDownLatchCyclicBarrierSemaphoreLockSupport相关的知识,希望对你有一定的参考价值。




CountDownLatch


假如有一个任务想要往下执行,但必须要等到其他的任务执行完毕后才可以。

比如你想要买套房子,但是呢你现在手上没有钱。你得等这个月工资发了、然后年终奖发了、然后朋友借你得钱还给你了、然后再给朋友借一部分才可以买,这种场景你就可以使用CountDownLatch。


CountDownLatch是JDK为我们提供的一个计数器,它的操作是原子操作,同一时间只能有一个线程去操作这个它。


我们先来看一下CountDownLatch的主要方法。

//构造方法,接收计数器的数量public CountDownLatch(int count)//持续等待计数器归零public void await()//最多等待unit时间单位内timeout时间public boolean await(long timeout, TimeUnit unit)//计数器减1public void countDown()//返回现在的计数器数量public long getCount()


下面是CountDownLatch的基本使用示例代码:

public class CountDownLatchDemo {    public static CountDownLatch countDownLatch = new CountDownLatch(5); static class ThreadDemo extends Thread { @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getId() + "完成任务"); countDownLatch.countDown(); }    } public static void main(String[] args) throws InterruptedException { for (int i = 0; i < 5; i++) { new ThreadDemo().start(); } countDownLatch.await(); System.out.println("全部完成任务"); }}


CyclicBarrier


相比较于CountDownLatch,CyclicBarrier可以完成前者的全部功能,但是相比前者,它的功能更加的强大。

  1. CyclicBarrier翻译过来的中文名称叫循环栅栏,顾名思义它可以循环使用

  2. CyclicBarrier还可以接收一个Runnable对象,当栅栏循环一次技术后会执行一次Runnable


我们来看一下CyclicBarrier的常用方法:

//构造方法,第一个参数为栅栏饿长度,第二个就是上方所说的Runnable对象public CyclicBarrier(int parties, Runnable barrierAction)public CyclicBarrier(int parties)//获取现在的数量public int getParties()//持续等待栅栏归零public int await()//最多等待unit时间单位内timeout时间public int await(long timeout, TimeUnit unit)



下面是CyclicBarrier的基本使用示例代码:


public class CyclicBarrierDemo {    public static CyclicBarrier cyclicBarrier = new CyclicBarrier(5,new FinallyThreadDemo()); static class ThreadDemo extends Thread { @Override public void run() { try { Thread.sleep(1000); System.out.println(Thread.currentThread().getId() + "完成任务"); cyclicBarrier.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } System.out.println("到达屏障点每个线程都会瞬时继续执行"); } } static class FinallyThreadDemo extends Thread { @Override public void run() { System.out.println("所有任务已经完成之后单独执行的任务!"); }    } public static void main(String[] args) throws InterruptedException { for (int i = 0; i < 10; i++) { new ThreadDemo().start();        } }}

观察打印结果我们可以发现:

当循环栅栏的任务执行完一轮以后,如果构造时传入了Runnable对象,则先执行Runnable对象,然后在瞬间释放所有任务的锁。

14完成任务15完成任务16完成任务17完成任务18完成任务所有任务已经完成之后单独执行的任务!到达屏障点每个线程都会瞬时继续执行到达屏障点每个线程都会瞬时继续执行到达屏障点每个线程都会瞬时继续执行到达屏障点每个线程都会瞬时继续执行到达屏障点每个线程都会瞬时继续执行19完成任务20完成任务21完成任务22完成任务23完成任务所有任务已经完成之后单独执行的任务!到达屏障点每个线程都会瞬时继续执行到达屏障点每个线程都会瞬时继续执行到达屏障点每个线程都会瞬时继续执行到达屏障点每个线程都会瞬时继续执行到达屏障点每个线程都会瞬时继续执行




Semaphore



在   一文中,我们了解了synch和读写锁,我们发现使用锁的时候一次只允许一条线程方法。那么有什么东西可以提供更强大的控制方法么?这个东西就是信号量。


信号量提供的主要方法:


//创建具有给定许可数的信号量Semaphore(int permits):构造方法,创建//拿走1个许可void acquire()//拿走多个许可void acquire(int n)//释放一个许可void release()//释放n个许可void release(int n)://当前可用的许可数int availablePermits()


下面来看使用示例:

public class SemaphoreThreadDemo { public static Semaphore semaphore = new Semaphore(5);
static class ThreadDemo extends Thread { @Override public void run() { try { semaphore.acquire(); System.out.println(Thread.currentThread().getId() + "号线程在"+System.currentTimeMillis()+"获取资源"); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); }finally { semaphore.release(); } } }
public static void main(String[] args) throws InterruptedException { for (int i = 0; i < 30; i++) { new ThreadDemo().start(); } }
}





LockSupport


我们在 和  两篇文章中使用过wait和notify实现了线程之间的协作,其实关于线程协作JDK还为我们提供了另外一个工具类LockSupport。


使用LockSupport实现等待通知功能时还不需要获取锁哦


先来看一下LockSupport的常用方法:

// 禁用当前线程static void park()// 如果参数线程的不可用,则使其可用。static void unpark(Thread thread)



来看一下示例代码:

public class LockSupportThreadDemo {    public static Thread thread; static class WaitThreadDemo extends Thread { @Override public void run() { System.out.println("WaitThread wait,time=" + System.currentTimeMillis()); thread = Thread.currentThread(); LockSupport.park(); System.out.println("WaitThread end,time=" + System.currentTimeMillis()); }    } static class NotifyThreadDemo extends Thread { @Override public void run() { System.out.println("NotifyThread notify,time=" + System.currentTimeMillis()); LockSupport.unpark(thread); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("NotifyThread end,time=" + System.currentTimeMillis()); }    } public static void main(String[] args) { WaitThreadDemo waitThreadDemo = new WaitThreadDemo(); NotifyThreadDemo notifyThreadDemo = new NotifyThreadDemo(); waitThreadDemo.start(); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } notifyThreadDemo.start();    }}



 收藏转发好看再走呗!

 

点击下方“阅读原文”查看源码!!!



以上是关于多线程工具类:CountDownLatchCyclicBarrierSemaphoreLockSupport的主要内容,如果未能解决你的问题,请参考以下文章

Java多线程——线程阻塞工具类LockSupport

Java多线程(线程池原子性并发工具类)

Java多线程并发工具类-信号量Semaphore对象讲解

java多线程10:并发工具类CountDownLatchCyclicBarrier和Semaphore

多线程编程学习九(并发工具类).

Java多线程同步工具类之Semaphore