CountDownLatch,一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。使用的时候,1、conutDown次数达到要求的时候,就会去直接执行await()后的函数,不会在进到while语句进行判断,2、不会像notify和wait方法,需要有锁的情况(等通知的线程完毕后,再去执行notify通知的另外一个线程),才可以接着执行 。
CountDownLatch主要方法
//构造函数 count 表示计数次数,调用多少次countDown后执行await阻塞的方法
public CountDownLatch(int count);
public void countDown();
public void await() throws InterruptedException
案例
有一个List集合,两个Thread共同操作这个List集合,当一个Thread写了5条记录后,通知另外一个线程,他完成了5条。另外一个线程获取5条信息后,执行自己的方法
使用CountDownLatch写法
package com.yellowcong.thread.demo;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
/**
* 创建日期:2017年10月5日 <br/>
* 创建用户:yellowcong <br/>
* 功能描述:
*/
public class ThreadListAdd2 {
private static final CountDownLatch cuCountDownLatch = new CountDownLatch(1);
public static void main(String[] args) {
final List<String> list = new ArrayList<String>();
//这个线程用于添加数据
Thread th1 = new Thread(new Runnable() {
public void run() {
for(int i=0;i<10;i++){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
list.add("yellowcong");
System.out.println(Thread.currentThread().getName()+"\t添加List");
if(i ==5){
//notify不释放当前线程的锁
cuCountDownLatch.countDown();
System.out.println("发送通知");
}
}
}
}, "t1");
Thread th2 = new Thread(new Runnable() {
public void run() {
// TODO Auto-generated method stub
while(true){
System.out.println(Thread.currentThread().getName()+"\t集合大小"+list.size());
if(list.size() != 5){
try {
cuCountDownLatch.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("收到通知\t当线程等于5的情况,停止线程");
throw new RuntimeException("停止线程");
}
}
}, "t2");
th2.start();
th1.start();
}
}
使用wait和notify方法写法
同步代码块的写法中,必须等写的线程将所有List写完,才会释放锁,notify不释放锁,wait释放锁,而且对于notify和wait最好放在while语句里面写,这样唤醒的时候,就不会没有直接判断就进入程序了
notify和notifyAll的区别:
1、notify()和notifyAll()都是Object对象用于通知处在等待该对象的线程的方法。
2、void notify(): 唤醒一个正在等待该对象的线程。
3、void notifyAll(): 唤醒所有正在等待该对象的线程。
两者的最大区别在于:
notifyAll使所有原来在该对象上等待被notify的线程统统退出wait的状态,变成等待该对象上的锁,一旦该对象被解锁,他们就会去竞争。
notify他只是选择一个wait状态线程进行通知,并使它获得该对象上的锁,但不惊动其他同样在等待被该对象notify的线程们,当第一个线程运行完毕以后释放对象上的锁,此时如果该对象没有再次使用notify语句,即便该对象已经空闲,其他wait状态等待的线程由于没有得到该对象的通知,继续处在wait状态,直到这个对象发出一个notify或notifyAll,它们等待的是被notify或notifyAll,而不是锁。
package com.yellowcong.thread.demo;
import java.util.ArrayList;
import java.util.List;
/**
* 创建日期:2017年10月5日 <br/>
* 创建用户:yellowcong <br/>
* 功能描述:
*/
public class ThreadListAdd {
private static final Object LOCK = new Object();
public static void main(String[] args) {
final List<String> list = new ArrayList<String>();
//这个线程用于添加数据
Thread th1 = new Thread(new Runnable() {
public void run() {
synchronized (LOCK) {
for(int i=0;i<10;i++){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
list.add("yellowcong");
System.out.println(Thread.currentThread().getName()+"\t添加List");
if(i ==5){
//notify不释放当前线程的锁
LOCK.notify();
System.out.println("发送通知");
}
}
}
}
}, "t1");
Thread th2 = new Thread(new Runnable() {
public void run() {
// TODO Auto-generated method stub
synchronized (LOCK) {
System.out.println(Thread.currentThread().getName()+"\t集合大小"+list.size());
if(list.size() != 5){
try {
LOCK.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("收到通知\t当线程等于5的情况,停止线程");
throw new RuntimeException("停止线程");
}
}
}, "t2");
th2.start();
th1.start();
}
}