`
suichangkele
  • 浏览: 199748 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

java并发编程-2

    博客分类:
  • java
阅读更多

以前讨论了线程之间的互斥,这里讨论线程之间的通信。线程之间的通信即A线程唤醒正在阻塞的其他线程,使其继续执行。最传统的方式即wait,notify,先上例子。

这里要实现的效果是A线程输出一次“AAA",然后B线程输出一下“BBB”,由于输出AAA或者BBB不是原子性操作(即输出不是一下子就能完成的,这期间CPU可能跑到其他线程上去执行)所以显然线程之间的互斥是必须的,我们这里使用synchronized关键字来解决线程之间的互斥。

 

public Class TheadCommunication1{

     public synchronized void out(String str){
		//这样做的目的纯粹是为了让其出现错误,以突出synchronized的作用。
		for(char c :str.toCharArray()){
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.print(c);	
		}
		System.out.println();
		
	}
	public static void main(String[] args) {
		final ThreadCommunication1 t = new ThreadCommunication1();
		new Thread(new Runnable() {
			public void run() {
				for(int i=0;i<50;i++){
					t.out("AAA");	
				}				
			}
		}).start();;
		new Thread(new Runnable() {
			public void run() {
				for(int i=0;i<50;i++){
					t.out("BBB");	
				}				
			}
		}).start();;
	}
     
}

 上面的代码可以实现线程之间的互斥,即当A线程执行out方法时B线程被阻塞,但是他没有实现线程之间的通信,即当A线程执行完out方法之后,接下来并不一定是B线程执行,可能A线程继续执行,也就是无法实现A B线程交替输出。所以必须使用线程之间的通信,下面使用了wait notify来实现

public class ThreadCommunication2 {

    private boolean toggle = true;
	
	public synchronized void outA() {
		while(toggle){
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
 		for(char c :"AAA".toCharArray()){
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.print(c);	
		}
		System.out.println();
		toggle = true;
		notify();
	}
	public synchronized void outB( ) {
		while(!toggle){
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
 		for(char c :"BBB".toCharArray()){
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.print(c);	
		}
		System.out.println();
		toggle = false;
		notify();
	}
	public static void main(String[] args) {
		final ThreadCommunication2 t = new ThreadCommunication2();
		new Thread(new Runnable() {
			public void run() {
				for(int i=0;i<50;i++){
					t.outA();
				}				
			}
		}).start();;
		new Thread(new Runnable() {
			public void run() {
				for(int i=0;i<50;i++){
					t.outB();
				}				
			}
		}).start();;
	}
}

 这里要解释一点为何用while不用if,if只判断一次而while判断多次,用while的原因是为了避免虚假唤醒,即有些线程可能会在不满足条件的时候虚假唤醒,所以用while能够避免这种情况。

 

这样就可以实现两个线程轮换的运行了。这里要加一点wait notify的解释。

wait notify必须用在synchronized代码块里(或者是方法),不然就会报错,wait也是获得的监视器,所以必须在同步代码块里。wait获得的监视器必须是synchronized同步的对象的监视器,如果捕获的是不同对象的监视器就会报错。所以只能这样:

//这样是可以的,因为synchronized和wait都是捕获的this(也就是当前对象)的监视器
synchronized void method1(){
       wait();
       ...
}

//这样也是可以的,都是捕获的lock的监视器
byte[] lock = new byte[0];//仅用于锁
void method2(){
    synchronized(lock){
        lock.wait();
         ...
   }
}
但是除了这两种情况交叉起来就会报错

 

 但是仍然不完美,因为notify是唤醒任意一个阻塞的线程,这里我们只有两个线程,所以唤醒的那个阻塞的线程一定是我们期待执行的线程,但是如果我们有3个线程呢?我们怎么指定唤醒哪个呢?所以这个时候就不能用synchronized  wait notify这套机制了,原因就是无法指定唤醒哪个线程。

 

 

假设有这样的一个需求:有三个线程ABC,A执行后B执行,然后C执行再A执行,这个时候就要用lock,condition类了。lock和之前的lock的用法一样,但是lock可以产生很多condition,调用condition的await和signal方法就相当于是之前的wait notify方法。但是区别的时就是可以区分多个不同的condition以指定哪个condition被唤醒,也就时执行哪个线程。上例子

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

public class ThreadCommunication3 {

    private int  toggle = 1;
    Lock lock = new ReentrantLock();
    Condition cA= lock.newCondition();
    Condition cB= lock.newCondition();
    Condition cC= lock.newCondition();
	
	public  void outA() {
		lock.lock();
		try {
			while(toggle != 1){
				try {
					cA.await();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
	 		for(char c :"AAA".toCharArray()){
				try {
					Thread.sleep(10);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.print(c);	
			}
			System.out.println();
			toggle = 2;
			cB.signal();//唤醒B
		} finally {
			lock.unlock();
		}
		
	}
	public  void outB() {
		lock.lock();
		try {
			while(toggle != 2){
				try {
					cB.await();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
	 		for(char c :"BBB".toCharArray()){
				try {
					Thread.sleep(10);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.print(c);	
			}
			System.out.println();
			toggle = 3;
			cC.signal();//唤醒C
		} finally {
			lock.unlock();
		}
		
	}
	public  void outC() {
		lock.lock();
		try {
			while(toggle != 3){
				try {
					cC.await();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
	 		for(char c :"CCC".toCharArray()){
				try {
					Thread.sleep(10);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.print(c);	
			}
			System.out.println();
			toggle = 1;
			cA.signal();//唤醒B
		} finally {
			lock.unlock();
		}
		
	}
	
	public static void main(String[] args) {
		final ThreadCommunication3 t = new ThreadCommunication3();
		new Thread(new Runnable() {
			public void run() {
				for(int i=0;i<50;i++){
					t.outA();
				}				
			}
		}).start();;
		new Thread(new Runnable() {
			public void run() {
				for(int i=0;i<50;i++){
					t.outB();
				}				
			}
		}).start();
		new Thread(new Runnable() {
			public void run() {
				for(int i=0;i<50;i++){
					t.outC();
				}				
			}
		}).start();;
	}
}

 

 

通过condition唤醒指定的线程就可以实现多个线程之间的通信了,并且可以执行唤醒的顺序。

 

 

 

 

分享到:
评论

相关推荐

    Java并发编程---synchronized关键字

    Java并发编程---synchronized关键

    62-Java并发编程实战

    62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java并发编程实战62-Java...

    Java并发编程-3.pdf

    Java并发编程中的多线程协作机制 在 Java 并发编程中,多线程协作机制是非常重要的一部分。多线程协作机制是指在多线程编程中,多个线程之间如何协作、同步和通信,以达到共同完成某个任务的目的。Java 提供了多种...

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

    Java并发编程-设计原则与模式 pdf格式

    Java并发编程实践-电子书

    Java并发编程实践-电子书-01章.pdf Java并发编程实践-电子书-02章.pdf Java并发编程实践-电子书-03章.pdf Java并发编程实践-电子书-04章.pdf Java并发编程实践-电子书-05章.pdf Java并发编程实践-电子书-06章.pdf ...

    JAVA并发编程-2-线程并发工具类

    JAVA并发编程-2-线程并发工具类一、Fork/Join1、分而治之与工作密取2、使用标准范式3、Fork/Join的同步用法4、Fork/Join的异步用法二、CountDownLatch三、CyclicBarrier四、Semaphore信号量五、Exchanger ...

    java并发编程-从入门到精通

    本教程“java并发编程-从入门到精通”旨在帮助你深入理解这个领域,并逐步提升你的编程能力。 首先,我们要理解Java并发的基础概念。并发是指一个程序中同时执行的多个线程,这在多核或多处理器系统中尤为常见。...

    阿里专家级并发编程架构师课程 彻底解决JAVA并发编程疑难杂症 JAVA并发编程高级教程

    阿里专家级并发编程架构师级课程,完成课程的学习可以帮助同学们解决非常多的JAVA并发编程疑难杂症,极大的提高...├─04-并发编程-并发协同-2.mp4 ├─L03-并发编程-并发协同.pdf (5)\并发编程05;目录中文件数:2个 ├

    Java并发编程-Doug Lea

    Java并发编程原汁原味英文版,Doug Lea大神经典著作, 内容:Concurrency Models, design forces, Java Designing objects for concurrency Immutability, locking, state dependence, containment, splitting ...

    java并发编程2

    Java并发编程是Java开发中的重要领域,特别是在多核处理器和分布式系统中,高效地利用并发可以极大地提升程序的性能和响应速度。以下是对标题和描述中所提及的几个知识点的详细解释: 1. **线程与并发** - **线程*...

    java并发编程实战源码,java并发编程实战pdf,Java

    《Java并发编程实战》是Java并发编程领域的一本经典著作,它深入浅出地介绍了如何在Java平台上进行高效的多线程编程。这本书的源码提供了丰富的示例,可以帮助读者更好地理解书中的理论知识并将其应用到实际项目中。...

    Java并发编程-并发容器1

    【Java并发编程-并发容器1】 在Java的并发编程中,容器的线程安全是至关重要的。HashMap在多线程环境下可能导致CPU利用率极高,因为它不是线程安全的。HashTable虽然提供了线程安全,但其同步机制导致并发性能较低。...

    Java 并发编程实战.pdf

    《Java并发编程实战》这本书是关于Java语言中并发编程技术的经典著作。它详细介绍了如何在Java环境中有效地实现多线程程序和并发控制机制。在Java平台上,由于其本身提供了强大的并发编程支持,因此,掌握并发编程...

    java并发编程-构建块

    "java并发编程-构建块"这个主题涵盖了使程序能够同时处理多个任务的关键概念和技术。在这个主题下,我们将深入探讨Java中用于构建高效并发应用的核心工具和概念。 1. **线程**:Java中的线程是并发编程的基础,每个...

    java并发编程艺术

    《Java并发编程艺术》这本书深入探讨了Java平台上的并发编程技术。并发编程是现代多核处理器环境下提升软件性能的关键手段,而Java语言提供了丰富的工具和API来支持这一领域。本书旨在帮助开发者理解和掌握如何在...

    java并发编程-超级大全整理

    总结,Java并发编程涵盖了大量的概念和技术,包括线程的创建、同步、通信以及并发工具的使用。理解和掌握这些知识点,是成为一名合格的Java并发程序员的基础。在实际开发中,应结合具体场景选择合适的并发策略,以...

    java高级技术JUC高并发编程教程2021(1.5G)

    03-JUC高并发编程-JUC概述和进程线程概念(2).mp4$ T/ H9 R! n2 l9 a b 04-JUC高并发编程-JUC概述和进程线程概念(3).mp4 05-JUC高并发编程-Synchronized复习和案例分析.mp4& R: O+ [6 A8 h1 L9 | 06-JUC高并发...

    《java 并发编程实战高清PDF版》

    《Java并发编程实战》是一本深入探讨Java平台并发编程的权威指南。这本书旨在帮助开发者理解和掌握在Java环境中创建高效、可扩展且可靠的多线程应用程序的关键技术和实践。它涵盖了从基本概念到高级主题的广泛内容,...

Global site tag (gtag.js) - Google Analytics