`
MouseLearnJava
  • 浏览: 463785 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Java并发编程-Condition使用实例

阅读更多

本文将简单介绍用于线程协作的Condition, 并给出一个例子,实现一个多线程题目--有三个线程分别打印A、B、C,请用多线程编程实现,在屏幕上循环打印10次ABCABC…


Condition是从JDK 1.5开始有的。API是这么描述的:





以上是Condition接口定义的方法,await()对应于Object#wait(),signal()对应于Object#notify(),signalAll()对应于Object#notifyAll()。

Condition是与Lock结合使用的,通过Lock.newCondition()方法能够创建与Lock绑定的Condition实例。

Lock和Condition的关系就如同 Object.wait(),Object.notify()方法和synchronized一样,它们都可以配合使用完成对多线程协作的控制。

JDK提供的ArrayBlockingQueue很好地诠释了Condition的使用。

public class ArrayBlockingQueue<E> extends AbstractQueue<E>
        implements BlockingQueue<E>, java.io.Serializable {

    /** Condition for waiting takes */
    private final Condition notEmpty;
    /** Condition for waiting puts */
    private final Condition notFull;


    /**
     * Inserts element at current put position, advances, and signals.
     * Call only when holding lock.
     */
    private void insert(E x) {
        items[putIndex] = x;
        putIndex = inc(putIndex);
        ++count;
        notEmpty.signal();
    }

    /**
     * Extracts element at current take position, advances, and signals.
     * Call only when holding lock.
     */
    private E extract() {
        final Object[] items = this.items;
        E x = this.<E>cast(items[takeIndex]);
        items[takeIndex] = null;
        takeIndex = inc(takeIndex);
        --count;
        notFull.signal();
        return x;
    }

    /**
     * Deletes item at position i.
     * Utility for remove and iterator.remove.
     * Call only when holding lock.
     */
    void removeAt(int i) {
        final Object[] items = this.items;
        // if removing front item, just advance
        if (i == takeIndex) {
            items[takeIndex] = null;
            takeIndex = inc(takeIndex);
        } else {
            // slide over all others up through putIndex.
            for (;;) {
                int nexti = inc(i);
                if (nexti != putIndex) {
                    items[i] = items[nexti];
                    i = nexti;
                } else {
                    items[i] = null;
                    putIndex = i;
                    break;
                }
            }
        }
        --count;
        notFull.signal();
    }

/**
     * Inserts the specified element at the tail of this queue, waiting
     * for space to become available if the queue is full.
     *
     * @throws InterruptedException {@inheritDoc}
     * @throws NullPointerException {@inheritDoc}
     */
    public void put(E e) throws InterruptedException {
        checkNotNull(e);
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == items.length)
                notFull.await();
            insert(e);
        } finally {
            lock.unlock();
        }
    }

    public E take() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == 0)
                notEmpty.await();
            return extract();
        } finally {
            lock.unlock();
        }
    }
... ... 
}


下面就使用Condition来完成一个线程面试题:有三个线程分别打印A、B、C,请用多线程编程实现,在屏幕上循环打印10次ABCABC…

程序如下:

package my.thread.test;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Logger;

/**
 * 题目:有三个线程分别打印A、B、C,请用多线程编程实现,在屏幕上循环打印10次ABCABC…
 * 
 * 本程序采用Lock和Condition来实现。
 * 
 * @author Eric
 * 
 */
public class ConditionExample {

	private Lock lock = new ReentrantLock();

	private Condition conditionA = lock.newCondition();
	private Condition conditionB = lock.newCondition();
	private Condition conditionC = lock.newCondition();

	/** 当前线程的名字 */
	private char currentThreadName = 'A';

	private static final Logger logger = Logger
			.getLogger("my.thread.test.OrderPrintTest");

	public static void main(String[] args) {

		ConditionExample ce = new ConditionExample();

		ExecutorService service = Executors.newFixedThreadPool(3);
		service.execute(ce.new ThreadA());
		service.execute(ce.new ThreadB());
		service.execute(ce.new ThreadC());

		service.shutdown();
	}

	private class ThreadA implements Runnable {
		public void run() {

			for (int i = 0; i < 10; i++) {
				lock.lock();
				try {
					while (currentThreadName != 'A') {
						try {
							/*
							 * 如果当前线程名字不是A,那么ThreadA就处理等待状态
							 */
							conditionA.await();
						} catch (InterruptedException e) {
							logger.severe(e.getLocalizedMessage());
						}
					}

					/*
					 * 打印出第几遍以及A信息
					 */
					System.out.println(String.format("第%d遍", i + 1));
					System.out.println("A");

					/*
					 * 将当前线程名置为B, 然后通知ThreadB执行
					 */
					currentThreadName = 'B';
					conditionB.signal();

				} finally {
					lock.unlock();
				}
			}
		}

	}

	private class ThreadB implements Runnable {
		public void run() {
			for (int i = 0; i < 10; i++) {
				lock.lock();
				try {
					while (currentThreadName != 'B') {
						try {
							/*
							 * 如果当前线程名字不是B,那么ThreadB就处理等待状态
							 */
							conditionB.await();
						} catch (InterruptedException e) {
							logger.severe(e.getLocalizedMessage());
						}
					}

					/*
					 * 打印信息B
					 */
					System.out.println("B");

					/*
					 * 将当前线程值置为C 并通过ThreadC来执行
					 */
					currentThreadName = 'C';
					conditionC.signal();

				} finally {
					lock.unlock();
				}
			}

		}

	}

	private class ThreadC implements Runnable {

		public void run() {
			for (int i = 0; i < 10; i++) {
				lock.lock();
				try {
					while (currentThreadName != 'C') {
						try {
							/*
							 * 如果当前线程名字不是C,那么ThreadC就处理等待状态
							 */
							conditionC.await();
						} catch (InterruptedException e) {
							logger.severe(e.getLocalizedMessage());
						}
					}

					/*
					 * 打印信息C
					 */
					System.out.println("C");
					System.out.println();

					/*
					 * 将当前线程值置为A 并通过ThreadA来执行
					 */
					currentThreadName = 'A';
					conditionA.signal();

				} finally {
					lock.unlock();
				}

			}
		}
	}
}


程序运行结果如下:
第1遍
A
B
C

第2遍
A
B
C

第3遍
A
B
C

第4遍
A
B
C

第5遍
A
B
C

第6遍
A
B
C

第7遍
A
B
C

第8遍
A
B
C

第9遍
A
B
C

第10遍
A
B
C

  • 大小: 16 KB
  • 大小: 51 KB
0
1
分享到:
评论

相关推荐

    Java并发编程--BlockingQueue.docx

    【Java并发编程--BlockingQueue详解】 BlockingQueue 是 Java 并发包(java.util.concurrent)中的一个接口,它扩展了 Queue 接口,并引入了线程安全的特性,特别适合于多线程环境下的数据共享。 BlockingQueue 的...

    Java并发编程书籍高清版

    书中可能包含了大量示例代码,通过实例解析Java并发编程中的常见问题,如死锁、活锁、饥饿现象,以及如何避免这些问题。此外,还可能涉及了Java内存模型(JMM)的理解,以及如何使用Lock接口和Condition来实现更细...

    Java并发编程设计原则和模式

    本资料“Java并发编程设计原则和模式”深入探讨了如何在Java环境中有效地进行并发处理,以充分利用系统资源并避免潜在的并发问题。 一、并发编程基础 并发是指两个或多个操作在同一时间段内执行,但并不意味着这些...

    java并发编程实战.zip

    总的来说,《Java并发编程实战》这本书不仅提供了丰富的理论知识,还通过大量的实例源码帮助读者将理论付诸实践,是Java开发者提升并发编程技能的必备参考。通过学习书中的内容,开发者能够更好地理解和掌握Java并发...

    Java并发编程实践源码

    1. **jcip-examples-src.jar**:这个JAR文件包含《Java并发编程实践》一书中的所有源代码实例,它是学习并发编程的重要资源。通过阅读和分析这些代码,我们可以深入理解Java并发API的用法,如`java.util.concurrent`...

    JAVA并发编程实践 EN(全)

    1. **并发基础**:介绍Java并发编程的基本概念,包括线程、进程、同步与互斥、死锁等。读者将了解Java中Thread类和Runnable接口的使用,以及如何创建和管理线程。 2. **线程安全**:讨论线程不安全的代码示例,以及...

    java并发编程实战源码-concurrent-programming:《Java并发编程实战》源码整理

    《Java并发编程实战》这本书是Java并发编程领域的一本经典之作,它深入浅出地讲解了如何在Java环境中高效、安全地进行多线程编程。源码整理集合`concurrent-programming-master`提供了书中示例代码,对于学习和理解...

    Java并发编程实践-07章-显示锁1

    在Java并发编程中,`Lock`接口和`ReentrantLock`类扮演着至关重要的角色。它们为多线程环境提供了更高级别的控制和灵活性,弥补了内置锁(也称为监视器锁或内部锁)的不足。`ReentrantLock`是Java 5.0引入的,作为对...

    Java并发编程ppt.rar

    Java并发编程是软件开发中的一个核心领域,尤其是在服务器端应用和多核处理器系统中,它的重要性日益凸显。这个“Java并发编程ppt”压缩包文件很可能包含了一套详细的讲解材料,帮助学习者理解并掌握Java环境下的多...

    java并发编程实战、驾校K1考试试卷批量生成源代码(单应用)

    总之,Java并发编程是一门深奥的学问,它涵盖了线程创建与管理、同步与通信、并发工具的使用等多个方面。通过学习和实践,你可以构建出更加健壮、高效的并发应用程序。对于"java并发编程实战"的学习,不仅要理解理论...

    Java并发编程实战

    Java并发编程实战 本书深入浅出地介绍了Java线程和并发,是一本完美的Java并发参考手册。书中从并发性和线程安全性的基本概念出发,介绍了如何使用类库提供的基本并发构建块,用于避免并发危险、构造线程安全的类及...

    Java并发编程.docx

    Java并发编程是开发高效应用程序的关键领域,特别是在多核处理器系统中。并发编程涉及的主要目标是确保线程安全、解决活跃性问题以及优化性能。 **1. 线程的三大性质** - **可见性**:当一个线程修改了共享变量,...

    java多线程编程实例 (源程序)

    - Condition接口:与Lock配合使用,提供更细粒度的线程间通信。 6. **线程优先级** - Java线程有10个优先级,默认是Thread.NORM_PRIORITY(5)。但优先级并不保证执行顺序,只是影响调度概率。 7. **守护线程...

    Java2.0网络多线程编程实例教程(光盘源代码)

    《Java2.0网络多线程编程实例教程》是一本由李荣贵等人编写的书籍,专注于Java2.0(即Java SE 2)平台下的网络编程和多线程技术。该书通过丰富的实例,旨在帮助读者深入理解和掌握这两项核心的Java开发技能。 在...

    商业编程-源码-让多个程序实例运行在同个进程空间的多个线程中.zip

    在商业编程中,这经常用于构建复杂的、高并发的应用,如服务器端程序、实时交易系统或大型游戏引擎等。 首先,理解线程的创建和管理。在大多数编程语言中,都有内置的库或者框架支持线程操作。例如,在Java中,我们...

    java并发编程专题(五)----详解(JUC)ReentrantLock

    Java并发编程中的ReentrantLock是Java并发包(java.util.concurrent,简称JUC)中的一个重要的锁机制,它是Lock接口的一个具体实现,提供了比synchronized更强大的锁定功能和更细粒度的控制。ReentrantLock的主要...

Global site tag (gtag.js) - Google Analytics