CountdownLatch
countdownLatch为多个线程整体到达条件时通知await的线程,即时序图如下:
image.png
由图中我们知道,执行的.countDown()方法的线程不会阻塞会接着干自己的事情,当thread1,2,3这3个线程都已经执行了countdown的时候就会通知 countdownLatch.await()上等待的线程。 其具体表现是一拨人等另一拨人。
具体伪代码交互模式为:
main(){
CountdownLatch countDownLatch = new CountDownLatch(5); //主线程
//countdown操作
new Thread( new Runnable(){ public void run(){ countDownLatch .countdown() }}).start();
new Thread( new Runnable(){ public void run(){ countDownLatch .countdown() }}).start();
//await操作,等待countdownLatch变成0,才继续执行
new Thread( new Runnable(){ public void run(){ countDownLatch .await() }}).start();
}
相关countlatchdown代码可以参考:https://blog.csdn.net/simonchi/article/details/47150173
CyclicBarrier
image.png由图我们知道,所有调用了CyclicBarrier.await()的线程会被阻塞,知道所有在Cyclic上的线程都await了后会整体释放一起恢复执行。其具体表现是等一拨人筹齐了再走。
其交互伪代码为:
CyclicBarrier cb = new CyclicBarrier(3)
new Thread( new Runnable(){ public void run(){ cb.await() }}).start();
new Thread( new Runnable(){ public void run(){ cb.await()}}).start();
//如果没有第三个线程执行cb.await()的话,那么 第一第二个线程永远在等待(除非被interrupted)
Exchanger
Exchange用于另个线程之间交换数据,如果一个线程thread1执行了Exchanger.exchange()方法另一个线程thread2还没有,那么thread1会被阻塞。其交互图如下:
image.png
Exchanger经常用于两个线程交换队列数据。
Final Exchanger<List<Integer>> exchanger = new Exchanger<List<Integer>>();
//两个线程交换队列
thread1 = new Thread
{
new Runnabler(){
.......
list1 =new Arraylist<String>();
list1 = exchanger.exchanger(list1)
}
}.start()
thread2 = new Thread
{
new Runnabler(){
.......
list2 =new Arraylist<String>();
list2 = exchanger.exchanger(list2)
}
}.start()
Semaphore
信号量用于控制线程之间的并发,比如5台机器8个工人操作每台机器只能被一个工人操作。那么可以通过semaphore来操作。
main(){
Semaphore semaphore = new Semaphore(5);
new Runnable()
{
semaphore.acquire();//如果没有获取到线程阻塞
.......do job....
semaphore.release();
}
}
//注意 semaphore.acquire()没有获取的话阻塞,如果不想阻塞可以替换成semaphore.tryacquire();//如果获取成功返回true,没有获取成功返回false
wait, notify,notifyAll
查看jdk Object.java 查看了释义,七对wait和notify解释如下:
wait:cause the current thread to wait until another thread to invoke the notify/notifyall method of this object.
1.首先什么是current thread即当前正在执行queue.wait()的线程 currentThread1。
2.我们需要通过另外一个线程 调用 queue.notify()来唤醒在 queue对象上等待的线程(有个等待队列)。
写代码需要注意以下几点:
1.wait和notify用于线程间协同,它是一个线程共享对象,所以需要加锁或者其他机制保证线程间可见和同步。
2.在调用wait的时候,要先判断是否条件不够。
具体以生产者消费者模型:
producer:
synchronized(queue)
{
condition = hold
queue.notifyall();
// 唤醒等待的线程(consumer线程,告诉他们有工作可以做了)去取队列数据工作
}
consumer:
synchronized(queue)
{
while (<condition does not hold>) //该consumer下次任务同样要判断
queue.wait(timeout, nanos);
// Perform action appropriate to condition ->这个是被唤醒之后执行的吧。
}
}
}
疑问:要consumer线程一直while检查条件,那么意思是说queue.wati()后consumer线程还会去进行下一次循环遍历么?
网友评论