`
woxiaoe
  • 浏览: 276726 次
  • 性别: 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线程:概念与原理 2 一、操作系统中线程和进程的概念 2 二、Java中的线程 3 三、Java中关于线程的名词解释 3 四、线程的状态转换和生命周期 4 Java线程:创建与启动 7 ...Java线程:线程之间的数据传递 58

    多线程学习笔记

    多线程学习笔记,通过平时的学习所做的一些笔记,希望对广大同仁有所帮助

    java学习笔记2(多线程)

    java学习笔记2(多线程)java学习笔记2(多线程)

    JAVA 多线程学习笔记

    NULL 博文链接:https://baobeituping.iteye.com/blog/1190260

    java线程 线程学习资料 java线程教程

    java线程 线程 教程 java线程教程 java线程学习资料 本教程有什么内容? 本教程研究了线程的基础知识— 线程是什么、线程为什么有用以及怎么开始编写使用线程的简单 程序。 我们还将研究更复杂的、使用线程的应用...

    线程 JAVA java线程 java线程第3版 java线程第2版第3版合集

    Java的线程工具易于使用,并且像Java中的其他东西一样可以在不同的平台之间移植。这是一件好事,因为如果没有线程,那么除了最简单的applet之外,几乎不可能编写出任何程序。如果你想使用Java,就必须学习线程。 ...

    java 线程总结笔记

    花费了一上午的时候 写了一些demo。认识到四种线程池的区别。上传到csdn 供以后学习

    java多线程编程总结

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

    Java多线程笔记

    多线程学习笔记,好资源。包括线程基础等知识多线程学习笔记,好资源。包括线程基础等知识

    Java线程讲解Java线程讲解

    Java线程讲解Java线程讲解Java线程讲解Java线程讲解Java线程讲解Java线程讲解Java线程讲解Java线程讲解Java线程讲解Java线程讲解

    Java多线程编程总结

    Java 线程系列博文总结word化,编目如下,欢迎互相学习交流: Java线程:概念与原理 Java线程:创建与启动 Java线程:线程栈模型与线程的变量 Java线程:线程状态的转换 Java线程:线程的同步与锁 Java线程:...

    Java线程详解大全

    Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程Java线程

    java多线程学习笔记

    这篇文档和对应的源代码 博文链接:https://interper56-sohu-com.iteye.com/blog/172303

    Java并发编程学习笔记 pdf 多线程编程

    Java并发编程学习笔记,研究JAVA并发多线程编程的一本教程,使用并发技术可以开发出并行算法,充分利用多处理器的计算能力,避免硬件资源浪费。目前,在JAVA并发编程方面的论述系统且内容详实的技术资料不太多,Java...

    基于java的开发源码-java多线程反射泛型及正则表达式学习笔记和源码.zip

    基于java的开发源码-java多线程反射泛型及正则表达式学习笔记和源码.zip 基于java的开发源码-java多线程反射泛型及正则表达式学习笔记和源码.zip 基于java的开发源码-java多线程反射泛型及正则表达式学习笔记和源码....

    Java线程Java线程Java线程Java线程

    Java线程Java线程Java线程Java线程Java线程Java线程

Global site tag (gtag.js) - Google Analytics