当我们在编写多线程的代码的时候,经常会考虑到多线程对共享资源的竞争问题。其中扮演着重要角色的就是Objcet的方法:wait、wait(long waitTime)、notify、notifyAll。开始学习多线程的时候,一直以为是当前线程调用这几个方法,结果老是报IllegalMonitorStateException异常,后查阅资料后发现是没有加锁的问题导致的,再仔细研究后发现,应该是调用竞争资源的相关方法,由竞争资源来等待和通知。下边简要说明下这几个方法的含义:
wait:当一个锁对象执行wait的时候,必须要取的这个锁对象的控制权,一般是放到synchronized(lock)代码中
wait(2000):当前线程每等待2秒的时候,就去检测是否可以获取到竞争资源的控制权,一旦取到竞争资源的控制权,当前线程就可以继续执行,负责继续等待。
notify:通知等待当前竞争资源的一个线程,如果有多个线程等待该资源,只会通知等待队列中的第一个相关线程(不会通知优先级比较高的线程)
notifyALl:通知所有等待该竞争资源的线程(也不会按照线程的优先级来执行)
在编写代码的时候,当我们需要调用以上的方法的时候,一定要对竞争资源进行加锁,如果不加锁的话,则会报 IllegalMonitorStateException 异常。下边是测试代码:
一、代码
package com.test.thread;
/**
* 测试线程的wait和notify方法
*
* @author rey
*
*/
public class TestThreadWait {
// 共享资源
private String[] lockObj = { "true" };
/**
* @param args
*/
public static void main(String[] args) {
TestThreadWait testMainThread = new TestThreadWait();
// 定义线程
NotifyThread notifyThread = testMainThread.new NotifyThread(
"notifyThread");
WatiThread wait01 = testMainThread.new WatiThread("wait01");
wait01.setPriority(2);
WatiThread wait02 = testMainThread.new WatiThread("wait02");
wait02.setPriority(3);
WatiThread wait03 = testMainThread.new WatiThread("wait03");
wait03.setPriority(4);
// 启动线程
notifyThread.start();
wait01.start();
wait02.start();
wait03.start();
}
// 定义通知线程
class NotifyThread extends Thread {
public NotifyThread(String _sThreadName) {
super(_sThreadName);
}
public void run() {
// 休眠5秒,给等待线程等待时间
try {
sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lockObj) {
System.out.println("线程[" + getName() + "]开始准备通知.....");
lockObj[0] = "false";
lockObj.notifyAll(); //该成lockObj.notify();则运行测试的时候进程没有结束,因为我们还有2个线程没有结束
System.out.println("线程[" + getName() + "]开始通知结束.....");
}
System.out.println("线程[" + getName() + "]运行结束.....");
}
}
// 定义等待的线程类
class WatiThread extends Thread {
public WatiThread(String _sThreadName) {
super(_sThreadName);
}
public void run() {
synchronized (lockObj) {
while (lockObj[0].equalsIgnoreCase("true")) {
System.out.println("线程[" + this.getName() + "]开始等待....");
long lWaitTime = System.currentTimeMillis();
try {
lockObj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
lWaitTime = System.currentTimeMillis() - lWaitTime;
System.out.println("线程[" + getName() + "]等待时间为:::"
+ lWaitTime);
}
}
System.out.println("线程[" + getName() + "]等待结束!!!");
}
}
}
二、运行测试用例后的一种可能结果(线程关闭的顺序可能不同,没有深入研究)
线程[wait01]开始等待....
线程[wait02]开始等待....
线程[wait03]开始等待....
线程[notifyThread]开始准备通知.....
线程[notifyThread]开始通知结束.....
线程[notifyThread]运行结束.....
线程[wait01]等待时间为:::5000
线程[wait01]等待结束!!!
线程[wait02]等待时间为:::5000
线程[wait02]等待结束!!!
线程[wait03]等待时间为:::5000
线程[wait03]等待结束!!!