`
247687009
  • 浏览: 173192 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

java多线程(三)线程之间的通信

阅读更多

一个新的线程一旦开启,就几乎不会和其他线程有啥关系了,线程内部是完全独立的。有些时候我们却又希望不同的两个或者多个线程之间能够互相的通信,举个列子。

       有这么一个要求。打印数到控制台,要求子线程打印5次,主线程打印10次,子线程又打印5次,主线程又10次。如此循环100次。这就需要线程之间通信了,子线程打完了,我能不能去通知主线程打,主线程打完了我能不能通知子线程打。这样子不就实现了要求了么?

首先第一点,这两个打印必须是互斥的,不然就全乱套了。所以按照互斥的思路得打如下代码

 

	new Thread(new Runnable() {
			@Override
			public void run() {
				for(int i=1;i<=100;i++){
					synchronized (Object.class) {
						for(int j=1;j<=5;j++){
							System.out.println("这是子线程第"+i+"次循环打印,打印的值为"+j);
						}
						
					}
				}
			}
		}).start();
		
		for(int i=1;i<=100;i++){
			synchronized (Object.class) {
			for(int j=1;j<=10;j++){
				System.out.println("这是主线程第"+i+"次循环打印,打印的值为"+j);
			}
			}
		}

   运行结果

 

 

这是主线程第1次循环打印,打印的值为1
这是主线程第1次循环打印,打印的值为2
这是主线程第1次循环打印,打印的值为3
这是主线程第1次循环打印,打印的值为4
这是主线程第1次循环打印,打印的值为5
这是主线程第1次循环打印,打印的值为6
这是主线程第1次循环打印,打印的值为7
这是主线程第1次循环打印,打印的值为8
这是主线程第1次循环打印,打印的值为9
这是主线程第1次循环打印,打印的值为10
这是子线程第1次循环打印,打印的值为1
这是子线程第1次循环打印,打印的值为2
这是子线程第1次循环打印,打印的值为3
这是子线程第1次循环打印,打印的值为4
这是子线程第1次循环打印,打印的值为5
//这应该打主线程才对呀,顺序给乱了。。。
这是子线程第2次循环打印,打印的值为1
这是子线程第2次循环打印,打印的值为2
这是子线程第2次循环打印,打印的值为3
这是子线程第2次循环打印,打印的值为4

   可以看到我们的手写的代码内部是正确了滴,就是外面的顺序不太多啊,java提供了一套等待唤醒机制来解决该问题。为了方便使用,讲两个打印方法封住进一个资源类中,外部只需要调用就好,不需要关注内部的实现细节。首先是jdk1.5之前的实现方式

//定义一个资源类
//具有两个互斥的方法 outSub outMain
class Resource{
	//定义一个标记表示现在该子线程执行还是main线程执行
	boolean isMain = false;
			
		public synchronized void outSub(int j){
			while(isMain){ //如果是main线程执行呢 就wait自己 使用while双重保险
				try {
					this.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			
			for(int i=1;i<=5;i++){
				System.out.println("这是子线程第"+i+"次循环打印,打印的值为"+j);
			}
			isMain=true;
			//this.notify();//唤醒线程 这里不一定唤醒的是main线程 只是随机唤醒线程池中的一个线程对象 
			//为了保证一定能够唤醒到对方 所以调用notifyAll()唤醒线程池中的所以休眠的线程
			this.notifyAll();
		}
		
		public synchronized void outMain(int j){
			while(!isMain){ //如果是子线程执行就wait 使用while双重保险
				try {
					this.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			
			for(int i=1;i<=10;i++){
				System.out.println("这是主线程第"+i+"次循环打印,打印的值为"+j);
			}
			isMain=false;
			//this.notify();//唤醒线程 这里不一定唤醒的是main线程 只是随机唤醒线程池中的一个线程对象 
			//为了保证一定能够唤醒到对方 所以调用notifyAll()唤醒线程池中的所以休眠的线程
			this.notifyAll();
			
		}
	
}

    在子线程和main线程中只需要调用即可

	public static void main(String[] args) {
		
		final Resource resource = new Resource();
		new Thread(new Runnable() {
			@Override
			public void run() {
				for (int i = 1; i <= 50; i++) {
					resource.outSub(i);
				}

			}
		}).start();

		for (int i = 1; i <= 50; i++) {
			resource.outMain(i);
		}

	}

   结果

这是子线程第1次循环打印,打印的值为1
这是子线程第2次循环打印,打印的值为1
这是子线程第3次循环打印,打印的值为1
这是子线程第4次循环打印,打印的值为1
这是子线程第5次循环打印,打印的值为1
这是主线程第1次循环打印,打印的值为1
这是主线程第2次循环打印,打印的值为1
这是主线程第3次循环打印,打印的值为1
这是主线程第4次循环打印,打印的值为1
这是主线程第5次循环打印,打印的值为1
这是主线程第6次循环打印,打印的值为1
这是主线程第7次循环打印,打印的值为1
这是主线程第8次循环打印,打印的值为1
这是主线程第9次循环打印,打印的值为1
这是主线程第10次循环打印,打印的值为1
这是子线程第1次循环打印,打印的值为2
这是子线程第2次循环打印,打印的值为2
这是子线程第3次循环打印,打印的值为2
这是子线程第4次循环打印,打印的值为2
这是子线程第5次循环打印,打印的值为
这是主线程第1次循环打印,打印的值为2
这是主线程第2次循环打印,打印的值为2
这是主线程第3次循环打印,打印的值为2
这是主线程第4次循环打印,打印的值为2
这是主线程第5次循环打印,打印的值为2
这是主线程第6次循环打印,打印的值为2
这是主线程第7次循环打印,打印的值为2
这是主线程第8次循环打印,打印的值为2
这是主线程第9次循环打印,打印的值为2
这是主线程第10次循环打印,打印的值为2

  在JDK1.5之后提供了新的等待唤醒机制来更好的解决问题,由于使用量的封装,所以不需要修改test代码只需要对资源类进行修改即可

 

//定义一个资源类
//具有两个互斥的方法 outSum outMain
class Resource{
	//定义一个标记表示现在该子线程执行还是main线程执行
	boolean isMain = false;
	Lock lock = new ReentrantLock();
	//在一个锁上门挂两个减少器,主要用于代理Object.wait() Object.notfiy() 
		//提供唤醒对方的机制
	final Condition sub = lock.newCondition();
	final Condition main = lock.newCondition();
			
		public  void outSub(int j){
			lock.lock(); //获取锁
			while(isMain){ //如果是main线程执行呢 就wait自己 使用while双重保险
				try {
					sub.await(); //等待 
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			
			try {
				for(int i=1;i<=5;i++){
					System.out.println("这是子线程第"+i+"次循环打印,打印的值为"+j);
				}
				isMain=true;
				//this.notify();//唤醒线程 这里不一定唤醒的是main线程 只是随机唤醒线程池中的一个线程对象 
				//为了保证一定能够唤醒到对方 所以调用notifyAll()唤醒线程池中的所以休眠的线程
//				this.notifyAll();
				main.signal(); //唤醒main线程
			} finally{
				lock.unlock();
			}
		}
		
		public  void outMain(int j){
			lock.lock(); //获取锁
			while(!isMain){ //如果是子线程执行就wait 使用while双重保险
				try {
					main.await();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			
			try {
				for(int i=1;i<=10;i++){
					System.out.println("这是主线程第"+i+"次循环打印,打印的值为"+j);
				}
				isMain=false;
				//this.notify();//唤醒线程 这里不一定唤醒的是main线程 只是随机唤醒线程池中的一个线程对象 
				//为了保证一定能够唤醒到对方 所以调用notifyAll()唤醒线程池中的所以休眠的线程
//				this.notifyAll();
				sub.signal();
			}finally{
				lock.unlock();
			}
			
		}
	
}

 

 

分享到:
评论

相关推荐

    java多线程通信图解

    java 多线程 其实就是每个线程都拥有自己的内存空间,多线程之间的通信,比例A线程修改了主内存(main方法的线程)变量,需要把A线程修改的结果同步到主线程中,这时B线程再从主线程获取该变量的值,这样就实现了...

    java多线程经典案例

    本案例将深入探讨Java多线程中的关键知识点,包括线程同步、线程通信和线程阻塞。 线程同步是为了防止多个线程同时访问共享资源,导致数据不一致。Java提供了多种同步机制,如synchronized关键字、Lock接口...

    Java多线程知识点总结

    Java多线程是Java编程语言中一个非常重要的概念,它允许开发者在一个程序中创建多个执行线程并行运行,以提高程序的执行效率和响应速度。在Java中,线程的生命周期包含五个基本状态,分别是新建状态(New)、就绪...

    java多线程的讲解和实战

    Java多线程是Java编程中的重要概念,尤其在如今的多核处理器环境下,理解并熟练掌握多线程技术对于提高程序性能和响应速度至关重要。本资料详细讲解了Java多线程的原理,并提供了丰富的实战代码,非常适合Java初学者...

    java多线程Demo

    Java多线程是Java编程中的一个重要概念,它允许程序同时执行多个任务,提高了程序的效率和响应速度。在Java中,实现多线程有两种主要方式:继承Thread类和实现Runnable接口。 1. 继承Thread类: 当我们创建一个新...

    深入浅出 Java 多线程.pdf

    在本文中,我们将深入浅出Java多线程编程的世界,探索多线程编程的基本概念、多线程编程的优点、多线程编程的缺点、多线程编程的应用场景、多线程编程的实现方法等内容。 一、多线程编程的基本概念 多线程编程是指...

    JAVA多线程编程技术PDF

    总结起来,“JAVA多线程编程技术PDF”涵盖了多线程的基本概念、同步机制、线程通信、死锁避免、线程池以及线程安全的集合类等内容。通过深入学习这份资料,开发者可以全面掌握Java多线程编程技术,提升程序的并发...

    JAVA单线程多线程

    多线程能够显著提高程序的并发性和效率,尤其是在处理I/O操作、网络通信等耗时操作时,可以避免阻塞主线程,从而提升整个系统的响应速度。 多线程的优点包括: 1. **提高系统利用率**:通过多线程可以充分利用多核...

    汪文君JAVA多线程编程实战(完整不加密)

    Java多线程允许程序同时执行多个独立的代码段,这在处理大数据、网络通信、用户界面更新等场景中尤其有用。书中详细介绍了Java多线程的核心概念,如线程的创建、启动、同步、协作以及生命周期管理。读者将学习如何...

    Java多线程机制(讲述java里面与多线程有关的函数)

    Java多线程机制是Java编程中至关重要的一部分,它允许程序同时执行多个任务,提升应用程序的效率和响应性。以下是对各个知识点的详细说明: 9.1 Java中的线程: Java程序中的线程是在操作系统级别的线程基础上进行...

    java 多线程并发实例

    在Java编程中,多线程并发是提升程序执行效率、充分利用多核处理器资源的重要手段。本文将基于"java 多线程并发实例"这个主题,深入探讨Java中的多线程并发概念及其应用。 首先,我们要了解Java中的线程。线程是...

    JAVAJAVA多线程教学演示系统论文

    《JAVA多线程教学演示系统》是一篇深入探讨JAVA多线程编程的论文,它针对教育领域中的教学需求,提供了一种生动、直观的演示方式,帮助学生更好地理解和掌握多线程技术。这篇论文的核心内容可能包括以下几个方面: ...

    Java多线程实现异步调用实例

    总之,Java多线程和异步调用是构建高效、响应迅速的应用程序的关键技术。通过合理利用这些工具和机制,开发者可以编写出能够充分利用多核处理器优势的代码,从而提高软件性能。在实际应用中,理解并熟练掌握这些概念...

    Java多线程练习题

    Java多线程是Java编程中的核心概念,它允许程序同时执行多个任务,提高了系统的效率和响应性。在Java中,多线程的实现主要通过两种方式:继承Thread类和实现Runnable接口。理解并掌握多线程的使用对于任何Java开发者...

    java tcp多线程通信

    Java TCP多线程通信是网络编程中的一个重要概念,它结合了Java的Socket编程与多线程技术,使得多个客户端能够同时与服务器进行交互。在Java中,TCP(传输控制协议)提供了一种可靠的数据传输方式,确保数据的有序、...

    java 多线程编程实战指南(核心 + 设计模式 完整版)

    《Java多线程编程实战指南》这本书深入浅出地讲解了Java多线程的核心概念和实战技巧,分为核心篇和设计模式篇,旨在帮助开发者掌握并应用多线程技术。 1. **线程基础** - **线程的创建**:Java提供了两种创建线程...

    Java多线程编程核心技术_完整版_java_

    Java多线程编程是Java开发中的重要组成部分,它允许程序同时执行多个任务,极大地提高了程序的效率和响应性。在Java中,多线程主要通过继承Thread类或实现Runnable接口来实现。本教程《Java多线程编程核心技术》将...

    Java多线程技术及其在网络编程中的应用.pdf

    ### Java多线程技术及其在网络编程中的应用 #### 引言 Java作为一种强大的面向对象的编程语言,由SUN公司开发,旨在支持分布式计算。它不仅具备简单的语法、面向对象的特点,还拥有跨平台的特性、高可靠性和安全性...

    Java多线程技术精讲

    总的来说,Java多线程技术包括线程的创建、管理、同步、通信以及异常处理等多个方面。深入理解和熟练掌握这些知识,对于编写高效、可靠的并发程序至关重要。在实际开发中,结合《Java多线程编程核心技术_完整版 带...

    Java多线程编程实战指南-核心篇

    《Java多线程编程实战指南-核心篇》是一本深入探讨Java并发编程的书籍,旨在帮助读者掌握在Java环境中创建、管理和同步线程的核心技术。Java的多线程能力是其强大之处,使得开发者能够在同一时间执行多个任务,提高...

Global site tag (gtag.js) - Google Analytics