◆
CountDownLatch
◆
假如有一个任务想要往下执行,但必须要等到其他的任务执行完毕后才可以。
比如你想要买套房子,但是呢你现在手上没有钱。你得等这个月工资发了、然后年终奖发了、然后朋友借你得钱还给你了、然后再给朋友借一部分才可以买,这种场景你就可以使用CountDownLatch。
CountDownLatch是JDK为我们提供的一个计数器,它的操作是原子操作,同一时间只能有一个线程去操作这个它。
我们先来看一下CountDownLatch的主要方法。
1 2 3 4 5 6 7 8 9 10 |
//构造方法,接收计数器的数量 public CountDownLatch(int count) //持续等待计数器归零 public void await() //最多等待unit时间单位内timeout时间 public boolean await(long timeout, TimeUnit unit) //计数器减1 public void countDown() //返回现在的计数器数量 public long getCount() |
下面是CountDownLatch的基本使用示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
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可以完成前者的全部功能,但是相比前者,它的功能更加的强大。
CyclicBarrier翻译过来的中文名称叫循环栅栏,顾名思义它可以循环使用
CyclicBarrier还可以接收一个Runnable对象,当栅栏循环一次技术后会执行一次Runnable
我们来看一下CyclicBarrier的常用方法:
1 2 3 4 5 6 7 8 9 |
//构造方法,第一个参数为栅栏饿长度,第二个就是上方所说的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的基本使用示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
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对象,然后在瞬间释放所有任务的锁。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
14完成任务 15完成任务 16完成任务 17完成任务 18完成任务 所有任务已经完成之后单独执行的任务! 到达屏障点每个线程都会瞬时继续执行 到达屏障点每个线程都会瞬时继续执行 到达屏障点每个线程都会瞬时继续执行 到达屏障点每个线程都会瞬时继续执行 到达屏障点每个线程都会瞬时继续执行 19完成任务 20完成任务 21完成任务 22完成任务 23完成任务 所有任务已经完成之后单独执行的任务! 到达屏障点每个线程都会瞬时继续执行 到达屏障点每个线程都会瞬时继续执行 到达屏障点每个线程都会瞬时继续执行 到达屏障点每个线程都会瞬时继续执行 到达屏障点每个线程都会瞬时继续执行 |
◆
Semaphore
◆
在 浅谈Java中的锁:Synchronized、重入锁、读写锁 一文中,我们了解了synch和读写锁,我们发现使用锁的时候一次只允许一条线程方法。那么有什么东西可以提供更强大的控制方法么?这个东西就是信号量。
信号量提供的主要方法:
1 2 3 4 5 6 7 8 9 10 11 12 |
//创建具有给定许可数的信号量 Semaphore(int permits):构造方法,创建 //拿走1个许可 void acquire() //拿走多个许可 void acquire(int n) //释放一个许可 void release() //释放n个许可 void release(int n): //当前可用的许可数 int availablePermits(): |
下面来看使用示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
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
◆
我们在 Hello,Thread 和 生产者消费者模型 两篇文章中使用过wait和notify实现了线程之间的协作,其实关于线程协作JDK还为我们提供了另外一个工具类LockSupport。
使用LockSupport实现等待通知功能时还不需要获取锁哦
先来看一下LockSupport的常用方法:
1 2 3 4 |
// 禁用当前线程 static void park() // 如果参数线程的不可用,则使其可用。 static void unpark(Thread thread) |
来看一下示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
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();
}
}
|
博客所有文章首发于公众号《Java学习录》转载请保留
扫码关注公众号即可领取2000GJava学习资源


本文详细介绍了Java中的四个多线程工具类:CountDownLatch用于同步多个线程,CyclicBarrier具备循环使用的特性,Semaphore用于控制并发线程数量,而LockSupport则提供了无锁的线程协作方式。通过实例代码展示了这些工具类的使用方法和关键功能。
1319

被折叠的 条评论
为什么被折叠?



