`

并发编程回顾:线程协作与Condition接口

 
阅读更多

原先多线程并发编程的学习笔记和代码整理一下贴上来。

---------------------------------

线程协作与Condition接口

一、线程协作

Java提供的线程之间协作方式主要有两种:

1、Object类中提供的wait、notify、notifyAll:

这种方式历史悠久,本篇只简单介绍一下。

相关知识点:

(1)wait()等待某个条件变化,这种条件将由另一个线程来改变,但不能因为测试这个条件而不断的空循环。所以wait()会在等待外部循环的时候挂起,并且只有在notify(),notifyAll()发生时,才会唤醒继续执行。

(2)必须从同步环境中调用wait()\notify()\notifyAll()。
在对象上调用wait()方法时,执行该代码的线程立即放弃它在对象上的锁。
当调用notify()时,并不意味着这时线程会放弃其锁,如果线程仍旧在完成同步代码,则线程在移出同步代码之前不会放弃锁,所以只调用notify()不意味着这时该锁将变得可用。
可以使用notifyAll()让所有线程冲出等待区,返回可运行状态。多个线程等待一个对象,使用notify()将只影响其中一个,具体哪个将由JVM决定。
(3)当使用wait()\notify()\notifyAll()时,几乎总有一个while(condition)循环包围着wait(),以便检查条件,并强制连续等待,直到条件满足为止。让时间到期,也可以令wait恢复执行,即使代码没有调用notify()或notifyAll()。因此,将wait()放入while循环,并且重新检查表示我们正在等待的事情的条件。我们确保不管因为什么原因醒来,当且仅当我们正在等待的事情还没有发生,将重新进入wait()。

2、javase5开始新加入的java.util.concurrent.locks包中Condition接口:

下面会重点介绍新接口的使用。

二、Condition接口

javase5新加入的java.util.concurrent.locks包中提供了Condition接口,按照JDK文档的描述:

Condition将Object监视器方法(wait、notify和notifyAll)分解成截然不同的对象,以便通过将这些对象与任意Lock实现组合使用,为每个对象提供多个等待set(wait-set)。其中,Lock替代了synchronized方法和语句的使用,Condition替代了Object监视器方法的使用。

Condition实现可以提供不同于Object监视器方法的行为和语义,比如受保证的通知排序,或者在执行通知时不需要保持一个锁

下面是一个示例:

这是一个给汽车涂蜡和抛光的例子,忘了当时是看了网上哪篇文章还是看了哪本书,觉得不错就记录下来了。

Condition使用起来与Object监视器方法比较类似,先定义一个汽车类:

class Car{
	private boolean waxOn = false;
	private Lock lock = new ReentrantLock();
	private Condition cond = lock.newCondition();
	
	public void buffed(){
		lock.lock();
		try{
			waxOn=false;
			cond.signalAll();//
		}finally{
			lock.unlock();
		}
	}
	public void waxed(){
		lock.lock();
		try{
			waxOn=true;
			cond.signalAll();//
		}finally{
			lock.unlock();
		}
	}
	public void waitingForWax() throws InterruptedException{
		lock.lock();
		try{
			while(waxOn==false){//汽车在抛光时一直等待
				cond.await();
			}
		}finally{
			lock.unlock();
		}
	}
	public void waitingForBuffing() throws InterruptedException{
		lock.lock();
		try{
			while(waxOn==true){//汽车在涂蜡时一直等待
				cond.await();
			}
		}finally{
			lock.unlock();
		}
	}
}

该类使用了ReentrantLock,并通过lock.newCondition();获取一个Condition。状态waxOn代表该车是否涂蜡,涂蜡之后抛光,因此waxed和buffed分别是涂蜡后和抛光后改变waxOn状态的操作。waitingForWax和waitingForBuffing代表等待涂蜡和等待抛光。 

然后定义一个涂蜡任务:

class WaxOn implements Runnable{
	private Car car;
	public WaxOn(Car c){
		this.car=c;
	}
	@Override
	public void run() {
		try{
			while(true){
				System.out.println("waxOn!");
				car.waxed();
				car.waitingForBuffing();
			}
		}catch(InterruptedException e){
			e.printStackTrace();
		}
		System.out.println("Ending WaxOn task.");
	}
}
这个任务一直循环给汽车涂蜡,不过每次涂蜡前要等汽车抛光完成之后再涂。

然后继续定义一个抛光任务:

class WaxOff implements Runnable{
	private Car car;
	public WaxOff(Car c){
		this.car=c;
	}
	@Override
	public void run(){
		try{
			while(true){
				car.waitingForWax();
				System.out.println("waxOff!");
				car.buffed();
			}
		}catch(InterruptedException e){
			e.printStackTrace();
		}
		System.out.println("Ending WaxOff task.");
	}
}

该任务循环给汽车抛光,但抛光前需要先等涂蜡结束,然后再抛光。

最后,开始给汽车抛光和涂蜡了吐舌头

Car car=new Car();
ExecutorService es = Executors.newCachedThreadPool();
es.execute(new WaxOff(car));
es.execute(new WaxOn(car));

控制台输出:

waxOn!
waxOff!
waxOn!
waxOff!
waxOn!
waxOff!
......

两个任务会循环不停的给汽车涂蜡和抛光,除非你手工停止这个程序。同时,涂蜡和抛光操作又不会同时进行,总是会等待另一个操作结束之后才开始,实现了2个线程的协作。

 

分享到:
评论

相关推荐

    Python并发编程详解:多线程与多进程及其应用场景

    内容概要:本文深入探讨了Python中的并发编程概念,特别是多线程与多进程的应用及其在不同负载情况下的优劣。通过对I/O密集型和CPU密集型任务的对比分析以及GIL(全局解释器锁)所带来的影响,介绍了具体实例,帮助...

    C++并发编程实战:示例源源码

    C++提供了多种同步原语,如互斥量(`std::mutex`)、条件变量(`std::condition_variable`)、信号量(`std::semaphore`)等。互斥量用于保护共享资源,确保同一时间只有一个线程访问;条件变量允许线程等待特定条件...

    java并发编程:线程基础

    Java并发编程中的线程基础是理解多线程编程的关键,它涵盖了从线程的创建到管理,再到线程间通信的全过程。多线程编程在处理高性能和高响应性的应用程序时至关重要,因为它允许程序在单个进程中同时执行多个任务,...

    Java并发编程:设计原则与模式(第二版).rar

    《Java并发编程:设计原则与模式(第二版)》是一本深入探讨Java平台上的多线程和并发编程的著作。本书旨在帮助开发者理解和掌握在Java环境中进行高效并发处理的关键技术与设计模式。以下是对该书内容的一些核心知识...

    Java并发编程:设计原则与模式(第二版)-3

    《Java并发编程:设计原则与模式(第二版)》是一本深入探讨Java多线程编程技术的权威著作。这本书详细阐述了在Java平台中进行高效并发处理的关键概念、设计原则和实用模式。以下是对该书内容的一些核心知识点的概述...

    java并发编程:设计原则与模式.rar

    《Java并发编程:设计原则与模式》是一本深入探讨Java多线程编程的书籍,它涵盖了并发编程中的关键概念、原则和模式。在Java中,并发处理是优化应用程序性能、提高资源利用率的重要手段,尤其在现代多核处理器的环境...

    Java并发编程:设计原则与模式(第二版)

    Java并发编程:设计原则与模式(第二版).pdf

    深入理解并发编程

    综上所述,《深入理解并发编程》一书应涵盖并发编程的基础理论、内存模型、同步机制、多线程编程技巧、常见问题的解决方案以及高效编程实践。掌握这些知识,能够帮助开发者在多核处理器时代编写出既高效又稳定的并发...

    一本经典的多线程书籍 Java并发编程 设计原则与模式 第二版 (英文原版)

    这本书深入探讨了Java平台上的多线程编程技术,为开发者提供了丰富的设计原则和模式,帮助他们理解和解决并发环境中的各种挑战。通过阅读这本书,读者可以提升在并发编程领域的专业知识,掌握构建高效、稳定、可扩展...

    Java并发编程:设计原则与模式(第二版)-3PDF

    《Java并发编程:设计原则与模式(第二版)》是一本深入探讨Java平台上的多线程和并发编程的权威著作。这本书旨在帮助开发者理解和掌握如何有效地编写可扩展且高效的并发程序。以下是书中涵盖的一些关键知识点: 1....

    构建高性能C++应用:并发编程与多线程处理-.md

    深入探讨了如何利用并发编程与多线程处理来构建高性能的C++应用。文章首先介绍了并发与并行的基本概念、线程与进程的区别,以及多线程的优势与挑战。接着,详细讲解了C++中支持并发编程的核心工具,包括`std::thread...

    Java并发编程-3.pdf

    多线程协作机制是指在多线程编程中,多个线程之间如何协作、同步和通信,以达到共同完成某个任务的目的。Java 提供了多种多线程协作机制,包括CountDownLatch、CyclicBarrier、Semaphore 等。 1. CountDownLatch ...

    Java多线程编程总结

    Java线程:并发协作-生产者消费者模型 Java线程:并发协作-死锁 Java线程:volatile关键字 Java线程:新特征-线程池 Java线程:新特征-有返回值的线程 Java线程:新特征-锁(上) Java线程:新特征-锁(下) Java...

    深入理解高并发编程-核心技术原理

    总的来说,这本书全面覆盖了高并发编程中的关键知识点,包括多线程原理、线程池实现、并发控制、分布式系统架构以及面试技巧,适合有志于提升并发编程能力的后端开发者阅读,尤其是对分布式锁和Java并发编程感兴趣的...

    C#中的并发编程模式:提升应用性能的关键策略

    本文将详细介绍C#中的并发编程模式,包括线程的使用、任务并行库(TPL)、异步编程模型(APM)以及数据并发的相关模式。 并发编程是提高应用程序性能的关键技术,C#提供了多种并发编程模式来帮助开发者编写高效、可...

    java线程与并发编程实践

    异常处理在多线程编程中同样重要。线程的中断(interrupt())和检查中断状态(isInterrupted()、interrupted())是处理异常情况的关键。同时,当一个线程抛出未捕获异常时,会终止该线程并通知其父线程。 在《java...

    基于Java并发编程的多线程同步与锁机制.zip

    基于Java并发编程的多线程同步与锁机制 项目简介 本项目旨在深入探讨Java并发编程中的多线程同步与锁机制,涵盖了从基础的线程创建、同步方法到高级的并发工具类如ReentrantLock、ReadWriteLock、Atomic类等的...

    Java 并发核心编程

    线程之间的协作是多线程编程中的另一个关键方面,涉及到线程之间的通信和同步。Java提供了多种机制来实现这一点: 1. **Wait/Notify**: `Object.wait()`和`Object.notify()`用于线程之间的简单同步。 2. **...

    Java并发编程的设计原则与模式

    本文将深入探讨Java并发编程的设计原则与模式,旨在帮助开发者理解并有效地应用这些原则和模式。 一、并发编程的基础概念 并发是指两个或多个操作在同一时间间隔内执行,而不是严格意义上的同一时刻。在Java中,...

Global site tag (gtag.js) - Google Analytics