`
woxiaoe
  • 浏览: 283572 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

Java线程学习笔记(八)线程之间的协作

    博客分类:
  • Java
阅读更多

wait()与notifyAll()

    调用sleep()的时候锁并没有被释放,调用yeild()也一样。当一个任务在方法里面遇到了对wait()的调用的时候,线程的执行被挂起,对象的锁被释放。因为wait()将释放锁,这就意味着另一个任务可以获得这个锁,因此在该对象中的其他synchronized方法可以再wait()期间被调用。

   

   wait() notify() notifyAll() 只能在同步控制方法或同步控制块里调用,否则运行时会出错,就是所,wait(),notify()和notifyAll()的任务在调用这些方法前必须拥有对象的锁。

 

下面为测试代码:

 

package com.woxiaoe.study.thread;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

class WaiteClient implements Runnable{

	@Override
	public void run() {
		try {
			System.out.println("进入WaitClient");
			synchronized (this) {
				wait();
			}
			
			System.out.println("hello world!");
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
}
class NotifyClient implements Runnable{
	private WaiteClient wc;
	public NotifyClient(WaiteClient wc) {
		this.wc = wc;
	}



	@Override
	public void run() {
		try {
			
			TimeUnit.SECONDS.sleep(3);
			synchronized (wc) {
				wc.notifyAll();
			}
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
	}
	
}

public class WaitNotifyTest {
	
	public static void main(String[] args) throws InterruptedException {
		ExecutorService exec = Executors.newCachedThreadPool();
		WaiteClient wc = new WaiteClient();
		NotifyClient nc = new NotifyClient(wc);
		exec.execute(wc);
		exec.execute(nc);
	/*	WaiteClient wc = new WaiteClient();
		NotifyClient nc = new NotifyClient(wc);
		Thread t1 = new Thread(new WaiteClient());
		Thread t2 = new Thread(new NotifyClient(wc));
		
		t1.start();
		t2.start();*/
		exec.shutdown();
		TimeUnit.SECONDS.sleep(5);
	}

}

 Output:

    进入WaitClient
    hello world!

 但如果改为如下者会报错

  

package com.woxiaoe.study.thread;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

class WaiteClient implements Runnable{

	@Override
	public void run() {
		try {
			System.out.println("进入WaitClient");
			//synchronized (this) {
				wait();
			//}
			
			System.out.println("hello world!");
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
}
class NotifyClient implements Runnable{
	private WaiteClient wc;
	public NotifyClient(WaiteClient wc) {
		this.wc = wc;
	}



	@Override
	public void run() {
		try {
			
			TimeUnit.SECONDS.sleep(3);
		//	synchronized (wc) {
				wc.notifyAll();
			//}
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
	}
	
}

public class WaitNotifyTest {
	
	public static void main(String[] args) throws InterruptedException {
		ExecutorService exec = Executors.newCachedThreadPool();
		WaiteClient wc = new WaiteClient();
		NotifyClient nc = new NotifyClient(wc);
		exec.execute(wc);
		exec.execute(nc);
	/*	WaiteClient wc = new WaiteClient();
		NotifyClient nc = new NotifyClient(wc);
		Thread t1 = new Thread(new WaiteClient());
		Thread t2 = new Thread(new NotifyClient(wc));
		
		t1.start();
		t2.start();*/
		exec.shutdown();
		TimeUnit.SECONDS.sleep(5);
	}

}

 

下面一个是模拟客户端与服务端通信的一个代码,主要为了实验线程间的协作,只有当客户端给服务端发请求后,服务端才向客户端响应。

package com.woxiaoe.study.thread;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * 模拟服务器的基本工作原理,测试wait 与 notifyAll
 * @author 小e
 *
 * 2010-4-26 下午09:51:15
 */
class Browser{
	boolean requestFlag ;
	SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	/**
	 * 得带浏览器给服务器发请求
	 * @return
	 * @throws InterruptedException 
	 */
	public synchronized void waitForRequest() throws InterruptedException{
		while(!requestFlag){
			wait();
		}
	}
	/**
	 * 等待服务器响应
	 * @throws InterruptedException 
	 */
	public synchronized void waitForResponse() throws InterruptedException{
		while(requestFlag){
			wait();
		}
	}
	public synchronized void request(){
		System.out.println(getTime() + " 客户端发送请求……");
		requestFlag = true;
		notifyAll();
	}
	public synchronized void response(){
		System.out.println(getTime() + " 服务端响应请求……");
		requestFlag = false;
		notifyAll();
	}
	private String getTime(){
		return sdf.format(new Date());
	}
}
class Request implements Runnable{
	private Browser browser;

	public Request(Browser browser) {
		this.browser = browser;
	}

	@Override
	public void run() {
		try {
			while (!Thread.interrupted()) {
				System.out.println("开始向服务端请求数据");
				browser.request();
				TimeUnit.MILLISECONDS.sleep(1000);// 模拟发送请求的时间消耗
				browser.waitForResponse();
			}
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			System.out.println("处理打断");
		}
		System.out.println("Request模块任务结束");
	}
	
	
}
class Response implements Runnable{
	private Browser browser;
	
	public Response(Browser browser) {
		this.browser = browser;
	}


	@Override
	public void run() {
		try {
			while (!Thread.interrupted()) {
				browser.waitForRequest();// 等待请求
				TimeUnit.MILLISECONDS.sleep(1000);// 模拟处理数据的时间消耗
				browser.response();
			}
		} catch (InterruptedException e) {
			System.out.println("处理打断");
		}
	}
	
}
public class Server {
	public static void main(String[] args) throws InterruptedException {
		Browser browser = new Browser();
		Request request = new Request(browser);
		Response response = new Response(browser);
		
		ExecutorService exec = Executors.newCachedThreadPool();
		
		exec.execute(request);
		exec.execute(response);
		
		TimeUnit.SECONDS.sleep(5);//模拟10秒
		exec.shutdownNow();
	}
}

 

Output:

  开始向服务端请求数据
2010-04-26 23:17:10 客户端发送请求……
2010-04-26 23:17:11 服务端响应请求……
开始向服务端请求数据
2010-04-26 23:17:11 客户端发送请求……
2010-04-26 23:17:12 服务端响应请求……
开始向服务端请求数据
2010-04-26 23:17:12 客户端发送请求……
2010-04-26 23:17:13 服务端响应请求……
开始向服务端请求数据
2010-04-26 23:17:13 客户端发送请求……
2010-04-26 23:17:14 服务端响应请求……
开始向服务端请求数据
2010-04-26 23:17:14 客户端发送请求……
处理打断
处理打断
Request模块任务结束

1
1
分享到:
评论

相关推荐

    java线程学习笔记

    Java线程学习笔记涉及了Java多线程编程的多个关键知识点,本篇知识点整理将详细解释每个概念及其在Java中的实现方式。 基本知识部分包含了Java线程编程的基础内容,它们是并发编程的基石。 任务Runnable是一个接口...

    java多线程笔记

    Java线程是多任务编程的重要组成部分,它允许程序同时执行多个独立的代码片段,从而提高程序的效率和响应性。本文将深入探讨Java线程的概念、原理以及如何在实际编程中进行有效管理。 首先,我们要了解操作系统中的...

    Java中线程同步和线程协作学习笔记

    在Java编程中,线程同步和线程协作是多线程编程的重要概念,确保了在并发环境下程序的正确性和数据的一致性。线程同步的主要目标是解决线程安全问题,即在多线程访问共享资源时避免数据的混乱,保证程序的可再现性。...

    Java线程编程学习笔记(二)

    这篇“Java线程编程学习笔记(二)”很可能是对Java并发编程深入探讨的一部分,特别是涉及多线程示例的实践应用。我们将从标题、描述以及标签来推测可能涵盖的知识点,并结合"Multi-Threads Demo"这一压缩包文件名来...

    java学习笔记markdown

    【Java学习笔记Markdown版】是针对Java初学者和进阶者的一份详尽教程,以Markdown格式编写,便于阅读和整理。Markdown是一种轻量级的标记语言,它允许用户使用易读易写的纯文本格式编写文档,然后转换成结构化的HTML...

    java多线程学习笔记

    - Java线程有10个优先级,从MIN_PRIORITY(1)到MAX_PRIORITY(10),默认优先级是NORM_PRIORITY(5)。 - 优先级高的线程并不保证一定先执行,线程调度还受到操作系统的限制。 6. **线程中断** - **interrupt()...

    java多线程笔记全手打

    本笔记全面涵盖了多线程的学习,包括基础理论和实践代码,旨在帮助开发者深入理解并掌握Java多线程技术。 一、线程基础知识 线程是操作系统分配CPU时间的基本单位,一个进程中可以包含多个线程。Java通过`Thread`类...

    张孝祥Java多线程与并发库高级应用笔记

    张孝祥的这套视频教程旨在深化Java线程技术的学习,帮助已有一定基础的开发者进一步提升技能。它并非面向完全的初学者,学习过程可能较为艰难,需反复研习方能深入理解。一旦掌握,学员将对Java线程技术有更为卓越的...

    Java分布式应用学习笔记05多线程下的并发同步器

    ### Java分布式应用学习笔记05多线程下的并发同步器 #### 1. 前言 在现代软件开发中,特别是在分布式系统和高性能计算领域,有效地管理多线程之间的协同工作至关重要。Java语言提供了丰富的工具和API来帮助开发者...

    马士兵多线程笔记.zip

    10. **线程间的通信**:Java的BlockingQueue接口和相关的类(如ArrayBlockingQueue、LinkedBlockingQueue)提供了一种线程间通信的方式,允许线程在生产数据和消费数据之间进行协作。 马士兵的多线程训练营资料1和...

    Java学习笔记和例子

    Java中的线程同步是指多个线程之间的协作和互斥,通过同步机制来确保线程安全。线程同步的主要特点是可以避免线程安全问题,例如通过锁机制来实现线程同步。 Java学习笔记和例子涵盖了Java语言的多个方面,包括...

    java分布式应用学习笔记05多线程下的并发同步器.pdf

    7. **并发工具类**:如CountDownLatch、CyclicBarrier、Semaphore等,它们在多线程协作中起到计数器、栅栏、信号量的作用,帮助控制线程的执行顺序和数量。 了解了这些基础工具后,我们需要掌握如何根据实际情况...

    Java编程思想学习笔记

    JVM的线程与内存关系主要阐述了Java线程与JVM线程的对应关系,以及它们与JVM内存区域之间的交互。每个Java线程都拥有自己的程序计数器(PC寄存器)和Java栈,而堆则是所有线程共享的内存区域。在JVM生命周期方面,从...

    《java学习》-java后端学习笔记.zip

    这份《java学习》-java后端学习笔记.zip压缩包包含了多个关键主题,旨在帮助初学者和有经验的开发者深入理解Java编程语言及其在后端应用中的实践。以下是这些主题的详细解析: 1. Git&GitHub.pdf:版本控制系统Git...

    多线程笔记.docx

    Java多线程是Java编程中不可或缺的部分,它允许程序同时执行多个任务,从而提升程序的效率和CPU的利用率。...通过学习和实践,开发者可以更好地驾驭Java的多线程特性,解决复杂的问题,提高软件的并发性能。

    JAVA并发编程实践-线程执行-学习笔记

    占式线程调度是Java和大多数现代操作系统采用的线程调度策略。在这种模式下,操作系统决定何时以及哪个线程将获得CPU的执行时间。线程的执行不是由线程自身控制,而是由操作系统通过时间片轮转或者优先级调度等方式...

    线程技术学习笔记.docx

    线程技术是计算机科学中的重要概念,特别是在Java编程语言中,多线程是实现高效并发执行的关键。本篇文章将深入探讨线程的基础知识,帮助初学者建立完整的线程技术知识架构。 首先,线程和进程是两个核心概念。线程...

    JUC多线程学习个人笔记

    然而,多线程也会带来线程安全性问题,如共享变量的更新一致性问题,以及线程之间的竞态条件。此外,过多的线程会消耗大量系统资源,可能导致性能下降。 7. **并发与并行**:并发是指多个线程在同一时间段内交替...

Global site tag (gtag.js) - Google Analytics