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();
    }
}