java多线程wait,notify,countDownLatch的一些简单应用

Posted xiaobinggan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java多线程wait,notify,countDownLatch的一些简单应用相关的知识,希望对你有一定的参考价值。

第一次写,错的地方,希望大家指出,谢谢!

wait ,notify都是Object中的方法:

1 ,他们必须配合synchronized关键字使用

2,wait方法释放锁,notify方法不释放锁

需求: 一个集合,2个线程,一个线程往集合中添加10个元素,另一个线程判断,如果集合中正好为5个元素时,就执行某段代码;

 1 public class ListAdd2 {
 2
 3     private static List list = new ArrayList();
 4     public void add() {
 5         list.add("hello world");
 6     }
 7 
 8     public int size() {
 9         return list.size();
10     }
11 
12     
13     public static void main(String[] args) {
14 
15         ListAdd2 listAdd = new ListAdd2();
16 
17         // 这边定义一个锁
18         final Object lock = new Object();
19 
20         Thread t1 = new Thread(new Runnable() {
21             @Override
22             public void run() {
23                 synchronized (lock) {
24                     System.out.println("t1启动");
25                     for (int i = 0; i < 10; i++) {
26                         try {
27                             listAdd.add();
28                             System.out.println("当前线程:"
29                                     + Thread.currentThread().getName()
30                                     + "添加了一个元素..");
31                             Thread.sleep(500);
32                             if (listAdd.size() == 5) {
33                                 System.out.println("t1发出通知");
34                                 lock.notify(); // 锁进行通知  不释放锁
35                             }
36                         }
37                         catch (InterruptedException e) {
38                             e.printStackTrace();
39                         }
40                     }
41                 }
42             }
43         });
44         
45         Thread t2 = new Thread(new Runnable() {
46 
47             @Override
48             public void run() {
49 
50                 synchronized (lock) {
51                     System.out.println("t2启动");
52                     if (listAdd.size() != 5) {
53                         try {
54                             lock.wait(); // 不等于 5  线程2 就在这里等待
55                         } catch (InterruptedException e) {
56                             e.printStackTrace();
57                         }
58                     }
59                     System.out.println("当前线程:"
60                             + Thread.currentThread().getName() + "收到通知线程停止..");
61                     throw new RuntimeException();
62                 }
63             }
64         });
65         t2.start(); 
66         t1.start();
67     }
68 }

打印结果如下:

t2启动
t1启动
当前线程:Thread-0添加了一个元素..
当前线程:Thread-0添加了一个元素..
当前线程:Thread-0添加了一个元素..
当前线程:Thread-0添加了一个元素..
当前线程:Thread-0添加了一个元素..
t1发出通知
当前线程:Thread-0添加了一个元素..
当前线程:Thread-0添加了一个元素..
当前线程:Thread-0添加了一个元素..
当前线程:Thread-0添加了一个元素..
当前线程:Thread-0添加了一个元素..
当前线程:Thread-1收到通知线程停止..
Exception in thread "Thread-1" java.lang.RuntimeException
at com.bjsxt.base.conn008.ListAdd2$2.run(ListAdd2.java:66)
at java.lang.Thread.run(Thread.java:748)

首先线程2先启动执行,获取了lock锁,在wait()方法,进行等待,并释放锁。

线程1 获取了lock锁,添加了5个元素后,发出了通知,唤醒锁,但是此时线程1 并没有释放锁,而是继续执行,等循环结束后,释放锁

线程2 继续运行,执行 后面的业务逻辑。

这里并不能满足我们的业务需求,我们希望集合中元素一旦有5个时,就执行线程2,而不是等到线程1全部执行完,才执行线程2;

所以这里我们要使用java.util.concurrent 包中的类 CountDownLatch

    public static void main(String[] args) {

        ListAdd2 listAdd = new ListAdd2();

        // 这边定义一个锁
        // final Object lock = new Object();
        CountDownLatch countDownLatch = new CountDownLatch(1); // 这里的 1 代表计数器为1
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
//                synchronized (lock) {
                    System.out.println("t1启动");
                    for (int i = 0; i < 10; i++) {
                        try {
                            listAdd.add();
                            System.out.println("当前线程:"
                                    + Thread.currentThread().getName()
                                    + "添加了一个元素..");
                            Thread.sleep(500);
                            if (listAdd.size() == 5) {
                                System.out.println("t1发出通知");
                                countDownLatch.countDown(); // 递减锁存器的计数,如果计数到达零,则释放所有等待的线程。
//                                lock.notify(); // 锁进行通知  不释放锁
                            }
                        }
                        catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
//            }
        });
        // 启动线程1
        Thread t2 = new Thread(new Runnable() {

            @Override
            public void run() {

//                synchronized (lock) {
                    System.out.println("t2启动");
                    if (listAdd.size() != 5) {
                        try {
                            countDownLatch.await();  // 线程等待
//                            lock.wait(); // 不等于 5  线程2 就在这里等待
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("当前线程:"
                            + Thread.currentThread().getName() + "收到通知线程停止..");
                    throw new RuntimeException();
                }
//            }
        });
        t2.start(); 
        t1.start();
    }

打印结果:  当集合中元素为5时,执行countDownLatch.countDown();  释放所有等待的线程,线程2就立刻执行了。

如果CountDownLatch countDownLatch = new CountDownLatch(2); //设置为2,则要执行2次,countDownLatch.countDown(),也就是将当计数器为0时,释放所有等待的线程

t2启动
t1启动
当前线程:Thread-0添加了一个元素..
当前线程:Thread-0添加了一个元素..
当前线程:Thread-0添加了一个元素..
当前线程:Thread-0添加了一个元素..
当前线程:Thread-0添加了一个元素..
t1发出通知
当前线程:Thread-0添加了一个元素..
当前线程:Thread-1收到通知线程停止..
Exception in thread "Thread-1" java.lang.RuntimeException
at com.bjsxt.base.conn008.ListAdd2$2.run(ListAdd2.java:69)
at java.lang.Thread.run(Thread.java:748)
当前线程:Thread-0添加了一个元素..
当前线程:Thread-0添加了一个元素..
当前线程:Thread-0添加了一个元素..
当前线程:Thread-0添加了一个元素..

 



































以上是关于java多线程wait,notify,countDownLatch的一些简单应用的主要内容,如果未能解决你的问题,请参考以下文章

Java多线程——wait方法和notify方法的详解

Java 多线程编程之:notify 和 wait 用法

Java多线程基础之wait,notify

[多线程]wait和notify

Java多线程_wait/notify/notifyAll方法

Java多线程系列 基础篇07 wait/notify/sleep/yield/join