JAVA线程间协作:Condition

    内置条件队列存在一些缺陷。每个内置锁都只能有一个相关联的条件队列,因而在像BounderBuffer这种类中,多个线程可能在同一个条件队列上等待不同的条件谓词,并且在最常见的加锁模式下公开条件队列对象。这些因素都使得无法满足在使用notifyAll时所有等待线程为统一类型的需求。如果想编写一个带有多个条件谓词的并发对象,或者想获得除了条件队列可见性之外的更多控制权,就可以使用显示的Lock和Condition而不是内置锁和条件队列,这是一种更灵活的选择。

    一个Condition和一个Lock关联在一起,就想一个条件队列和一个内置锁相关联一样。要创建一个Condition,可以在相关联的Lock上调用Lock.newCondition方法。正如Lock比内置加锁提供了更为丰富的功能,Condition同样比内置条件队列提供了更丰富的功能:在每个锁上可存在多个等待、条件等待可以是可中断的或者不可中断的、基于时限的等待,以及公平的或非公平的队列操作。

    与内置条件队列不同的是,对于每个Lock,可以有任意数量的Condition对象。Condition对象继承了相关的Lock对象的公平性,对于公平的锁,线程会依照FIFO顺序从Condition.await中释放。

Condition接口:

public interface Condition{
    void await() throws InterruptedException;
    boolean await(long time, TimeUnit unit) throws InterruptedException;
    long awaitNanos(long nanosTimeout) throws InterruptedException;
    void awaitUniterruptibly();
    boolean awaitUntil(Date deadline) throws InterruptedException;
    void signal();
    void signalAll();
}

    注意:在Condition对象中,与wait,notify和notifyAll方法对于的分别是await,signal,signalAll。但是,Condition对Object进行了扩展,因而它也包含wait和notify方法。一定要确保使用的版本——await和signal.
官方使用方法如下:

class BoundedBuffer
{
    final Lock lock = new ReentrantLock();
    final Condition notFull = lock.newCondition();
    final Condition notEmpty = lock.newCondition();

    final Object[] items = new Object[100];
    int putptr, takeptr, count;

    public void put(Object x) throws InterruptedException
    {
        lock.lock();
        try
        {
            while (count == items.length)
                notFull.await();
            items[putptr] = x;
            if (++putptr == items.length)
                putptr = 0;
            ++count;
            notEmpty.signal();
        }
        finally
        {
            lock.unlock();
        }
    }

    public Object take() throws InterruptedException
    {
        lock.lock();
        try
        {
            while (count == 0)
                notEmpty.await();
            Object x = items[takeptr];
            if (++takeptr == items.length)
                takeptr = 0;
            --count;
            notFull.signal();
            return x;
        }
        finally
        {
            lock.unlock();
        }
    }
}

    或者通过一个实际的例子来解释Condition的用法:
    我们要打印1-9这0个数字,由A线程先打印1-3,然后由B线程打印4-6,然后再由A线程打印7-9.我们采用Condition来演示解决方法:

package com.cooperation;

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

public class TestCondition
{
    private static int value = 1;
    private Lock lock = new ReentrantLock();
    private Condition Condition456 = lock.newCondition();
    private Condition Condition789 = lock.newCondition();

    class ThreadA implements Runnable{
        @Override
        public void run()
        {
            try
            {
                lock.lock();
                System.out.println("首先输出1-3");
                while(value<=3)
                {
                    System.out.println(value++);
                }
                Condition456.signal();
            }
            finally
            {
                lock.unlock();
            }

            try
            {
                lock.lock();
                while(value<=6)
                {
                    Condition789.await();
                }
                System.out.println("输出7-9");
                while(value<=9)
                {
                    System.out.println(value++);
                }
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
            finally
            {
                lock.unlock();
            }

        }
    }

    class ThreadB implements Runnable{
        @Override
        public void run()
        {
            try
            {
                lock.lock();
                while(value<=3)
                {
                    Condition456.await();
                }
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
            finally{
                lock.unlock();
            }

            try{
                lock.lock();
                System.out.println("输出4-6");
                while(value<=6)
                {
                    System.out.println(value++);
                }
                Condition789.signal();
            }
            finally
            {
                lock.unlock();
            }
        }
    }

    public static void main(String[] args)
    {
        TestCondition test = new TestCondition();
        Thread threadA = new Thread(test.new ThreadA());
        Thread threadB = new Thread(test.new ThreadB());
        threadA.start();
        threadB.start();
    }

}

输出结果:

首先输出1-3
1
2
3
输出4-6
4
5
6
输出7-9
7
8
9

    如果需要采用Object方法的wait,notify,notifyAll方法实现这个实例可以参考:http://outofmemory.cn/java/java.util.concurrent/thread-sync-with-object-wait-notify-notifyAll
    同样可以扩张,ThreadA打印123,ThreadB打印456,再让ThreadA打印789,最后然ThreadB打印10 11 12.如下:

package com.cooperation;

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

public class TestCondition
{
    private static int value = 1;
    private Lock lock = new ReentrantLock();
    private Condition Condition456 = lock.newCondition();
    private Condition Condition789 = lock.newCondition();
    private Condition Condition101112 = lock.newCondition();

    class ThreadA implements Runnable{
        @Override
        public void run()
        {
            try
            {
                lock.lock();
                System.out.println("首先输出1-3");
                while(value<=3)
                {
                    System.out.println(value++);
                }
                Condition456.signal();
            }
            finally
            {
                lock.unlock();
            }

            try
            {
                lock.lock();
                while(value<=6)
                {
                    Condition789.await();
                }
                System.out.println("输出7-9");
                while(value<=9)
                {
                    System.out.println(value++);
                }
                Condition101112.signal();
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
            finally
            {
                lock.unlock();
            }

        }
    }

    class ThreadB implements Runnable{
        @Override
        public void run()
        {
            try
            {
                lock.lock();
                while(value<=3)
                {
                    Condition456.await();
                }
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
            finally{
                lock.unlock();
            }

            try{
                lock.lock();
                System.out.println("输出4-6");
                while(value<=6)
                {
                    System.out.println(value++);
                }
                Condition789.signal();
            }
            finally
            {
                lock.unlock();
            }

            try
            {
                lock.lock();
                while(value<=9)
                {
                    Condition101112.await();
                }
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
            finally{
                lock.unlock();
            }

            try{
                lock.lock();
                System.out.println("输出10-12");
                while(value<=12)
                {
                    System.out.println(value++);
                }
            }
            finally
            {
                lock.unlock();
            }
        }
    }

    public static void main(String[] args)
    {
        TestCondition test = new TestCondition();
        Thread threadA = new Thread(test.new ThreadA());
        Thread threadB = new Thread(test.new ThreadB());
        threadA.start();
        threadB.start();
    }
}

输出结果:

首先输出1-3
1
2
3
输出4-6
4
5
6
输出7-9
7
8
9
输出10-12
10
11
12
时间: 2024-09-15 07:57:15

JAVA线程间协作:Condition的相关文章

JAVA线程间协作:wait.notify.notifyAll

    JAVA的进程同步是通过synchronized()来实现的,需要说明的是,JAVA的synchronized()方法类似于操作系统概念中的互斥内存块,在JAVA中的Object类型中,都是带有一个内存锁的,在有线程获取该内存锁后,其它线程无法访问该内存,从而实现JAVA中简单的同步.互斥操作.明白这个原理,就能理解为什么synchronized(this)与synchronized(static XXX)的区别了,synchronized就是针对内存区块申请内存锁,this关键字代表类

线程间协作的两种方式:wait、notify、notifyAll和Condition

在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者模型:当队列满时,生产者需要等待队列有空间才能继续往里面放入商品,而在等待的期间内,生产者必须释放对临界资源(即队列)的占用权.因为生产者如果不释放对临界资源的占用权,那么消费者就无法消费队列中的商品,就不会让队列有空间,那么生产者就会一直无限等待下去.因此,一般情况下,当队列满时,会让生产者交出对临界资源的占用权,并进入挂起状态.然后等待消费者消费了商品,然后消费者通知生产者队列有空间了.同样地,当

java-并发-线程间协作的两种方式:wait、notify、notifyAll和Condition

线程之间的协作.比如说最经典的生产者-消费者模型:当队列满时,生产者需要等待队列有空间才能继续往里面放入商品,而在等待的期间内,生产者必须释放对临界资源(即队列)的占用权.因为生产者如果不释放对临界资源的占用权,那么消费者就无法消费队列中的商品,就不会让队列有空间,那么生产者就会一直无限等待下去.因此,一般情况下,当队列满时,会让生产者交出对临界资源的占用权,并进入挂起状态.然后等待消费者消费了商品,然后消费者通知生产者队列有空间了.同样地,当队列空时,消费者也必须等待,等待生产者通知它队列中有

Java线程间通讯概述

这个故事源自一个很简单的想法:创建一个对开发人员友好的.简单轻量的线程间通讯框架,完全不 用锁.同步器.信号量.等待和通知,在Java里开发一个轻量.无锁的线程内通讯框架:并且也没有队列 .消息.事件或任何其他并发专用的术语或工具. 只用普通的老式Java接口实现POJO的通讯. 它可能跟Akka的类型化actor类似,但作为一个必须超级轻量,并且要针对单台多核计算机进行优化的 新框架,那个可能有点过了. 当actor跨越不同JVM实例(在同一台机器上,或分布在网络上的不同机器上)的进程边界时,

Java线程间的通信方式详解_java

本总结我对于JAVA多线程中线程之间的通信方式的理解,主要以代码结合文字的方式来讨论线程间的通信,故摘抄了书中的一些示例代码,具体内容如下 ①同步 这里讲的同步是指多个线程通过synchronized关键字这种方式来实现线程间的通信. 参考示例: public class MyObject { synchronized public void methodA() { //do something.... } synchronized public void methodB() { //do so

java线程间通信

线程通信的目标是使线程间能够互相发送信号.另一方面,线程通信使线程能够等待其他线程的信号. 例如,线程B可以等待线程A的一个信号,这个信号会通知线程B数据已经准备好了.本文将讲解以下几个JAVA线程间通信的主题: 1.通过共享对象通信 2.忙等待 3.wait(),notify()和notifyAll() 4.丢失的信号 5.假唤醒 6.多线程等待相同信号 7.不要对常量字符串或全局对象调用wait() 1.通过共享对象通信 线程间发送信号的一个简单方式是在共享对象的变量里设置信号值.线程A在一

Java多线程之线程间协作 notify与wait的使用

(转载请注明出处:http://blog.csdn.net/buptgshengod) 1.背景        Java多线程操作运用很广,特别是在android程序方面.线程异步协作是多线程操作的难点也是关键,也是找工作面试经常考到的地方.下面分享一下我的使用心得. 介绍几个关键字: synchronized:线程锁,使得系统只执行当前线程. notifyAll():唤醒其它被锁住的线程 wait():挂起线程 ExecutorService exec=Executors.newCachedT

java线程间通信[实现不同线程之间的消息传递(通信),生产者和消费者模型]

线程通信,线程之间的消息传递: 多个线程在操作同一个资源,但对共享资源的操作动作不同:它们共享同一个资源,互为条件,相互依赖,相互通信让任务向前推进. 线程的同步,可以解决并发更新同一个资源,实现线程同步;但不能用来实现线程间的消息传递. 线程通信生产者和消费者和仓库是个典型模型: 生产者:没有生产之前通知消费者等待,生产产品结束之后,马上通知消费者消费 消费者:没有消费之前通知生产者等待,消费产品结束之后,通知生产者继续生产产品以供消费 线程通信:使用java中Object中提供的: publ

Java中使用wait()与notify()实现线程间协作

使用wait()与notify()/notifyAll()可以使得多个任务之间彼 此协作. 1. wait()与notify()/notifyAll() 调用sleep()和yield()的时候锁并没有被释放,而调用wait() 将释放锁.这样另一个任务(线程)可以获得当前对象的锁,从而 进入它的synchronized方法中.可以通过notify()/notifyAll(), 或者时间到期,从wait()中恢复执行. 只能在同步控制方法或同步块中调用wait().notify()和 notif