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添加了一个元素..

原文地址:https://www.cnblogs.com/xiaobinggan/p/8401492.html

时间: 2024-11-09 03:11:19

java多线程wait,notify,countDownLatch的一些简单应用的相关文章

Java多线程之~~~使用CountDownLatch来同步多个线程实现一个任务

在多线程开发中,经常会遇到这样的问题,比如,一个线程需要其他的一些辅助线程完成指定的一些任务后才能开 启. 类似于一个主线程正在运行,他需要其他分支线程完成一些任务后才能激活他来启动剩下的任务,这里就可以使用 Java自带的CountDownLatch这个类来帮我们实现这样的效果.   这个类初始化的时候会指定一个数字,这就是需要等 待的资源的数量,每一个资源到位的时候,就调用他的countDown函数,这样就会将资源减一,知道这个资源数字变成 0的时候 ,就会叫醒主线程,来完成剩下的功能,下面

Java多线程系列——计数器 CountDownLatch

简介: CountDownLatch 是一个非常实用的多线程控制工具类,通常用来控制线程的等待,它可以让某个线程等待直到倒计时结束 CountDownLatch 提供了两个主要的方法,await().countDown(). await:使当前线程阻塞,等待计数器为 0 countDown:计数器减一,计数为零时,释放所有在等待的线程 实例: public class CountDownLatchDemo implements Runnable { static final CountDownL

java多线程基本概述(六)——简单生产者消费者模式

在线程里,生产者就是生产数据的线程,消费者就是消费数据的线程.在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据.同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者.为了解决这个问题于是引入了生产者和消费者模式.下面实现一个简单的生产者消费者模式: 1.一个消费者一个生产者循环消费生产 package soarhu; import java.util.ArrayList; import java.util.Lis

Java多线程之---用 CountDownLatch 说明 AQS 的实现原理

本文基于 jdk 1.8 . CountDownLatch 的使用 前面的文章中说到了 volatile 以及用 volatile 来实现自旋锁,例如 java.util.concurrent.atomic 包下的工具类.但是 volatile 的使用场景毕竟有限,很多的情况下并不是适用,这个时候就需要 synchronized 或者各种锁实现了.今天就来说一下几种锁的实现原理. 先来看一个最简单的 CountDownLatch 使用方法,例子很简单,可以运行看一下效果.CountDownLat

java多线程编程之CountDownLatch

java.util.concurrent.CountDownLatch这个类里面的主要方法为: 1.countDown(),Decrements the count of the latch, releasing all waiting threads if the count reaches zero. 2.await(),Causes the current thread to wait until the latch has counted down to zero, unless the

java多线程wait notify join

wait notify 几个注意点: wait 与 notify/notifyAll 方法必须在同步代码块中使用,即要先对调用对象加锁. 当线程执行wait()时,会把当前的锁释放,然后让出CPU,进入等待状态. 当执行notify/notifyAll方法时,会唤醒一个处于等待该 对象锁 的线程,然后继续往下执行,直到执行完退出对象锁锁住的区域(synchronized修饰的代码块)后再释放锁. 从这里可以看出,notify/notifyAll()执行后,并不立即释放锁,而是要等到执行完临界区中

Java多线程--wait(),notify(),notifyAll()的用法

忙等待没有对运行等待线程的 CPU 进行有效的利用(而且忙等待消耗cpu过于恐怖,请慎用),除非平均等待时间非常短.否则,让等待线程进入睡眠或者非运行状态更为明智,直到它接收到它等待的信号. Java 有一个内建的等待机制来允许线程在等待信号的时候变为非运行状态.java.lang.Object 类定义了三个方法,wait().notify()和 notifyAll()来实现这个等待机制. 但在使用wait().notify()和 notifyAll()必须获取该对象的锁,否则的话会抛异常Ill

Java多线程_wait/notify/notifyAll方法

关于这三个方法,我们可以查询API得到下列解释: wait():导致当前的线程等待,直到其他线程调用此对象的notify( ) 方法或 notifyAll( ) 方法或者指定的事件用完 notify():唤醒在此对象监视器上等待的单个线程 notifyAll():唤醒在此对象监视器上等待的所有线程 我们需要注意的点(1)wait().notify/notifyAll() 方法是Object的本地final方法,无法被重写. (2)wait() 与 notify/notifyAll 方法必须在同步

Java 多线程 :入门(1)- 简单试验ExecuteorService

首先,根据其他文章提到的,我也实验了的Runnable跟Callable的差别: 1)Callable接口的call()方法有返回值,这样方便处理“需要将一个对象加工并返回”的需求(Runnable的run()没有返回值,但可以通过回调的方式在run()内部解决): 2)都使用ExecutorService来submit()时,均返回Future<T>,但前者的future.get()为空,后者可以有内容: 试验一下Executors.newFixedThreadPool(), 代码如下: p