Java并发多线程编程——Condition接口的理解及使用

Posted 小志的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java并发多线程编程——Condition接口的理解及使用相关的知识,希望对你有一定的参考价值。

一、Condition接口的理解

  • Condition是个接口,基本的方法就是await()和signal()方法;
  • Condition用来替代传统的Object的wait()、notify()实现线程间的协作。相比使用Object的wait()、notify(),使用Condition的await()、signal()这种方式实现线程间协作更加安全和高效;
    - Condition对象是依赖于lock对象的,也就是说condition对象需要通过lock对象进行创建出来; 调用Condition的await()和signal()方法,都必须在lock保护之内,就是说必须在lock.lock()和lock.unlock之间才可以使用。

二、Condition接口结构及常用方法

在这里插入图片描述

  • await() :造成当前线程在接到信号或被中断之前一直处于等待状态。
  • awaitUninterruptibly() :造成当前线程在接到信号之前一直处于等待状态。【注意:该方法对中断不敏感】。
  • awaitNanos(long nanosTimeout) :造成当前线程在接到信号、被中断或到达指定等待时间之前一直处于等待状态。返回值表示剩余时间,如果在nanosTimesout之前唤醒,那么返回值 = nanosTimeout - 消耗时间,如果返回值 <= 0 ,则可以认定它已经超时了。
  • await(long time, TimeUnit unit) :造成当前线程在接到信号、被中断或到达指定等待时间之前一直处于等待状态。
  • awaitUntil(Date deadline) :造成当前线程在接到信号、被中断或到达指定最后期限之前一直处于等待状态。如果没有到指定时间就被通知,则返回true,否则表示到了指定时间,返回返回false。
  • signal() :唤醒一个等待线程。该线程从等待方法返回前必须获得与Condition相关的锁。
  • signal()All :唤醒所有等待线程。能够从等待方法返回的线程必须获得与Condition相关的锁。

三、使用Object类中的wait()、notifyAll()实现多个线程按顺序执行示例

1、案例场景

多个线程,按照线程顺序依次循环执行。

2、代码

package com.xz.thread.t15;

/**
 * @description: 创建a线程类
 * @author: xz
 * @create: 2021-05-24 21:08
 */
public class Atarget implements Runnable{

    private Demo demo;

    public Atarget(Demo demo){
        this.demo =demo;
    }

    @Override
    public void run() {
        while(true){
            demo.a();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

package com.xz.thread.t15;

/**
 * @description: 创建b线程类
 * @author: xz
 * @create: 2021-05-24 21:14
 */
public class Btarget implements Runnable{

    private Demo demo;

    public Btarget(Demo demo){
        this.demo =demo;
    }

    @Override
    public void run() {
        while(true){
            demo.b();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }


}

package com.xz.thread.t15;

/**
 * @description: 创建c线程类
 * @author: xz
 * @create: 2021-05-24 21:16
 */
public class Ctarget implements Runnable{

    private Demo demo;

    public Ctarget(Demo demo){
        this.demo =demo;
    }

    @Override
    public void run() {
        while(true){
            demo.c();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

package com.xz.thread.t15;


/**
 * @description:
 * @author: xz
 * @create: 2021-05-23 22:12
 */
public class Demo {

    private int signal;

    public synchronized void a(){
        while (signal != 0){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("【a】线程执行");
        signal++;
        notifyAll();
    }

    public synchronized void b(){
        while (signal != 1){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("【b】线程执行");
        signal++;
        notifyAll();
    }

    public synchronized void c(){
        while (signal != 2){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("【c】线程执行");
        signal =0;
        notifyAll();
    }

    public static void main(String[] args) {
        Demo d =new Demo();
        Atarget a = new Atarget(d);
        Btarget b = new Btarget(d);
        Ctarget c = new Ctarget(d);

        new Thread(a).start();
        new Thread(b).start();
        new Thread(c).start();
    }
}

2、运行main函数,输出结果如下:

在这里插入图片描述

四、使用Condition接口中的await()、signal()现多个线程按顺序执行示例

1、案例场景

多个线程,按照线程顺序依次循环执行。

2、代码

package com.xz.thread.t16;

/**
 * @description: 创建a线程类
 * @author: xz
 * @create: 2021-05-24 21:08
 */
public class Atarget implements Runnable{

    private Demo demo;

    public Atarget(Demo demo){
        this.demo =demo;
    }

    @Override
    public void run() {
        while(true){
            demo.a();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

package com.xz.thread.t16;

/**
 * @description: 创建b线程类
 * @author: xz
 * @create: 2021-05-24 21:14
 */
public class Btarget implements Runnable{

    private Demo demo;

    public Btarget(Demo demo){
        this.demo =demo;
    }

    @Override
    public void run() {
        while(true){
            demo.b();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }


}

package com.xz.thread.t16;

/**
 * @description: 创建c线程类
 * @author: xz
 * @create: 2021-05-24 21:16
 */
public class Ctarget implements Runnable{

    private Demo demo;

    public Ctarget(Demo demo){
        this.demo =demo;
    }

    @Override
    public void run() {
        while(true){
            demo.c();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

package com.xz.thread.t16;


import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @description:
 * @author: xz
 * @create: 2021-05-23 22:32
 */
public class Demo {

    private int signal;

    Lock lock = new ReentrantLock();
    Condition a = lock.newCondition();
    Condition b = lock.newCondition();
    Condition c = lock.newCondition();


    public void a(){
        lock.lock();
        while (signal != 0){
            try {
                a.await();//线程等待
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("【a】方法执行");
        signal++;
        b.signal();//唤醒b方法
        lock.unlock();
    }

    public void b(){
        lock.lock();
        while (signal != 1){
            try {
                b.await();//线程等待
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("【b】方法执行");
        signal++;
        c.signal();//唤醒c方法
        lock.unlock();
    }

    public void c(){
        lock.lock();
        while (signal != 2){
            try {
               c.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("【c】方法执行");
        signal =0;
        a.signal();//唤醒a方法
        lock.unlock();
    }

    public static void main(String[] args) {
        Demo d =new Demo();
        Atarget a = new Atarget(d);
        Btarget b = new Btarget(d);
        Ctarget c = new Ctarget(d);

        new Thread(a).start();
        new Thread(b).start();
        new Thread(c).start();
    }



}

2、运行main函数,输出结果如下:

在这里插入图片描述

以上是关于Java并发多线程编程——Condition接口的理解及使用的主要内容,如果未能解决你的问题,请参考以下文章

Java——多线程高并发系列之Condition接口中的await()signal()signAll()方法

Java——多线程高并发系列之Condition接口中的await()signal()signAll()方法

JAVA并发编程实战12使用condition实现多线程下的有界缓存先进先出队列

Java多线程与并发编程——ConditionCallable&Future

Java多线程与并发编程——ConditionCallable&Future

Java多线程与并发编程——ConditionCallable&Future