Java多线程之wait和notify

标签: java 多线程 wait | 发表时间:2015-10-27 16:54 | 作者:
出处:http://www.iteye.com

最近在看Java特种兵,看到多线程部分,对wait和notify不是很理解,于是写了代码来帮助理解。特此记录下来,以供回顾。

             wait方法通过参数可以指定等待的时长。如果没有指定参数,默认一直等待直到被通知。notify方法是通知某个正在等待这个对象的控制权的线程可以继续运行。

 

调用wait方法时候,必须加上synchronized同步块,不然会抛出java.lang.IllegalMonitorStateException异常

public class WaitAndNotify {
private final static Object object = new Object();
	
	static class ThreadA extends Thread{
		public void run(){
			//通过object对象进行加锁
				System.out.println(Thread.currentThread().getName()+":start...");
				try {
					//调用当前对象的wait方法
					Thread.currentThread().wait();
				} catch (InterruptedException e) {
					System.out.println("aaaa");
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName()+":end...");
		}
	}
	public static void main(String[] args) throws InterruptedException {
		ThreadA t1 = new ThreadA();
		t1.setName("t1");
		t1.start();
		Thread.sleep(100);
		System.out.println(t1.getName()+":"+t1.getState());
	}
}

  

 

public class WaitAndNotify {
private final static Object object = new Object();
	
	static class ThreadA extends Thread{
		public void run(){
			//通过object对象进行加锁
			synchronized (object) {
				System.out.println(Thread.currentThread().getName()+":start...");
				try {
					//调用当前对象的wait方法
					Thread.currentThread().wait();
				} catch (InterruptedException e) {
					System.out.println("aaaa");
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName()+":end...");
			}
		}
	}
	public static void main(String[] args) throws InterruptedException {
		ThreadA t1 = new ThreadA();
		t1.setName("t1");
		t1.start();
		Thread.sleep(100);
		System.out.println(t1.getName()+":"+t1.getState());
	}
}

 
这段程序是报异常:

t1:start...
Exception in thread "t1" java.lang.IllegalMonitorStateException
	at java.lang.Object.wait(Native Method)
	at java.lang.Object.wait(Unknown Source)
	at Thread.WaitAndNotify$ThreadA.run(WaitAndNotify.java:15)
t1:TERMINATED

 
原因是:锁对象和调用wait方法的对象不是同一个。wait方法是Object的方法,对象和调用wait方法的对象必须是同一个对象。
以下是修改后的正确代码:

public class WaitAndNotify {
private final static Object object = new Object();
	
	static class ThreadA extends Thread{
		public void run(){
			//通过object对象进行加锁
			synchronized (this) {
				System.out.println(Thread.currentThread().getName()+":start...");
				try {
					//调用当前对象的wait方法
					Thread.currentThread().wait();
				} catch (InterruptedException e) {
					System.out.println("aaaa");
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName()+":end...");
			}
		}
	}
	public static void main(String[] args) throws InterruptedException {
		ThreadA t1 = new ThreadA();
		t1.setName("t1");
		t1.start();
		Thread.sleep(100);
		System.out.println(t1.getName()+":"+t1.getState());
	}
}

 或者:

public class WaitAndNotify {
private final static Object object = new Object();
	
	static class ThreadA extends Thread{
		public void run(){
			//通过object对象进行加锁
			synchronized (object) {
				System.out.println(Thread.currentThread().getName()+":start...");
				try {
					//调用object对象的wait方法
					object.wait();
				} catch (InterruptedException e) {
					System.out.println("aaaa");
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName()+":end...");
			}
		}
	}
	public static void main(String[] args) throws InterruptedException {
		ThreadA t1 = new ThreadA();
		t1.setName("t1");
		t1.start();
		Thread.sleep(100);
		System.out.println(t1.getName()+":"+t1.getState());
	}
}

 

 上面两段代码虽然正确执行了,但是由于线程状态一直是WAITING,会一直等待下去,这个时候,我们使用调用notify方法,让线程继续执行下去

public class WaitAndNotify {
private final static Object object = new Object();
	
	static class ThreadA extends Thread{
		public void run(){
			//通过object对象进行加锁
			synchronized (object) {
				System.out.println(Thread.currentThread().getName()+":start...");
				try {
					//调用object对象的wait方法
					object.wait();
				} catch (InterruptedException e) {
					System.out.println("aaaa");
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName()+":end...");
			}
		}
	}
	public static void main(String[] args) throws InterruptedException {
		ThreadA t1 = new ThreadA();
		t1.setName("t1");
		t1.start();
		Thread.sleep(100);
		System.out.println(t1.getName()+":"+t1.getState());
		//和wait方法一样,需要加锁
		synchronized (object) {
			object.notify();
		}
	}
}

 



已有 0 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [java 多线程 wait] 推荐:

Java多线程之wait()和notify()

- - CSDN博客推荐文章
直接看测试代码吧,细节之处,详见注释.  * Java多线程之wait()和notify()的妙用 .  * @see 问题:同时启动两个线程和同时启动四个线程,控制台打印结果是不同的 .  * @see      同时启动两个线程时,控制台会很规律的输出1010101010101010 .  * @see      同时启动四个线程时,控制台起初会规律的输出10101010,一旦某一刻输出一个负数,那么后面的输出就会"一错再错" .

java多线程设计wait/notify机制

- - CSDN博客推荐文章
  当线程A获得了obj锁后,发现条件condition不满足,无法继续下一处理,于是线程A就wait() , 放弃对象锁..   之后在另一线程B中,如果B更改了某些条件,使得线程A的condition条件满足了,就可以唤醒线程A:.   # 调用obj的wait(), notify()方法前,必须获得obj锁,也就是必须写在synchronized(obj) {…} 代码段内.

Java多线程之wait和notify

- - ITeye博客
最近在看Java特种兵,看到多线程部分,对wait和notify不是很理解,于是写了代码来帮助理解.              wait方法通过参数可以指定等待的时长. 如果没有指定参数,默认一直等待直到被通知. notify方法是通知某个正在等待这个对象的控制权的线程可以继续运行. 调用wait方法时候,必须加上synchronized同步块,不然会抛出java.lang.IllegalMonitorStateException异常.

Java Sleep() 与 Wait()的机制原理与区别

- - CSDN博客推荐文章
Java中的多线程是一种抢占式的机制而不是分时机制. 线程主要有以下几种状态:可运行,运行,阻塞,死亡. 抢占式机制指的是有多个线程处于可运行状态,但是只有一个线程在运行.        当有多个线程访问共享数据的时候,就需要对线程进行同步.        Thread类的方法:sleep(),yield()等.

[转载]java之yield(),sleep(),wait()区别详解

- - 移动开发 - ITeye博客
使当前线程(即调用该方法的线程)暂停执行一段时间,让其他线程有机会继续执行,但它并不释放对象锁. 也就是说如果有synchronized同步快,其他线程仍然不能访问共享数据. 例如有两个线程同时执行(没有synchronized)一个线程优先级为MAX_PRIORITY,另一个为MIN_PRIORITY,如果没有Sleep()方法,只有高优先级的线程执行完毕后,低优先级的线程才能够执行;但是高优先级的线程sleep(500)后,低优先级就有机会执行了.

Java Thread多线程

- - CSDN博客推荐文章
Java Thread多线程. Java 多线程例子1 小例子. super("zhuyong");//设置线程的名字,默认为“TestThread”. Java 多线程例子2 前台线程(用户线程) 后台线程(守护线程 ). 1,setDaemon(true)后就是后台线程(守护线程 ),反之就是前台线程(用户线程).

Java多线程之synchronized

- - CSDN博客推荐文章
这里通过三个测试类阐述了synchronized应用的不同场景. 首先是最基本的synchronized Method的使用.  * @see 概述:Java中的每个对象都有一个锁(lock)或者叫做监视器(monitor) .  * @see 说明:当synchronized关键字修饰一个方法时,则该方法为同步方法 .

java多线程总结

- - Java - 编程语言 - ITeye博客
在java中要想实现多线程,有两种手段,一种是继续Thread类,另外一种是实现Runable接口. 对于直接继承Thread的类来说,代码大致框架是:. class 类名 extends Thread{. * @author Rollen-Holt 继承Thread类,直接调用run方法.             System.out.println(name + "运行     " + i);.

Java多线程学习

- - CSDN博客编程语言推荐文章
  线程是一种轻量级的进程,它和进程一样拥有独立的执行控制,由操作系统负责调度,区别在于线程没有独立的存储空间,而是和所属进程中的其它线程共享一个存储空间,这使得线程间的通信远较进程简单. 即多个线程可以同时执行,就像有多条流水线一样,可以同时进行工作,是并发执行的.   程序是由进程组成的,进程是由线程组成的.

Java多线程(二)同步

- - CSDN博客编程语言推荐文章
如果你的java基础较弱,或者不大了解java多线程请先看这篇文章 java多线程(一)线程定义、状态和属性. 同步一直是java多线程的难点,在我们做android开发时也很少应用,但这并不是我们不熟悉同步的理由. 希望这篇文章能使更多的人能够了解并且应用java的同步. 在多线程的应用中,两个或者两个以上的线程需要共享对同一个数据的存取.