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模块任务结束

你可能感兴趣的:(java,thread,工作,浏览器)