wait()方法和notify()方法使用时的注意事项

/ 多线程 / 没有评论 / 264浏览
/**
* 管理用户请求
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-15 10:44
* @since 1.0.0
*/
public class RequestAdmin extends Thread {

private Object lock;

public RequestAdmin(Object lock) {
this.lock = lock;
}

@Override
public void run() {
try {
System.out.println(String.format("start wait time: %s", System.currentTimeMillis()));
lock.wait();
System.out.println(String.format("end wait: %s", System.currentTimeMillis()));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* 用户请求
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-15 10:44
* @since 1.0.0
*/
public class RequestUser extends Thread {


private Object lock;

public RequestUser(Object lock) {
this.lock = lock;
}

@Override
public void run() {
System.out.println(String.format("start notify time: %s", System.currentTimeMillis()));
lock.notify();
System.out.println(String.format("end notify: %s", System.currentTimeMillis()));
}
}
/**
* 测试类
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-15 10:49
* @since 1.0.0
*/
public class RequestRun {
public static void main(String[] args) throws InterruptedException {
Object lock = new Object();
RequestAdmin requestAdmin = new RequestAdmin(lock);
RequestUser requestUser = new RequestUser(lock);
requestAdmin.start();
for (int i = 3; i > 0; i--) {
System.out.println(String.format("倒计时:%s", i));
Thread.sleep(1000);
}
requestUser.start();
}
}
start wait time: 1489730354433
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
倒计时:3
	at java.lang.Object.wait(Native Method)
	at java.lang.Object.wait(Object.java:502)
	at RequestAdmin.run(RequestAdmin.java:21)
倒计时:2
倒计时:1
Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
start notify time: 1489730357489
	at java.lang.Object.notify(Native Method)
	at RequestUser.run(RequestUser.java:21)

我们看程序出线了异常。原因是我们没有添加synchronized关键字,所以线程获取不到锁,而直接抛出的异常。

/**
* 管理用户请求
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-15 10:44
* @since 1.0.0
*/
public class RequestAdmin extends Thread {

private Object lock;

public RequestAdmin(Object lock) {
this.lock = lock;
}

@Override
public void run() {
try {
synchronized (lock) {
System.out.println(String.format("start wait time: %s", System.currentTimeMillis()));
lock.wait();
System.out.println(String.format("end wait: %s", System.currentTimeMillis()));
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* 测试类
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-15 10:49
* @since 1.0.0
*/
public class RequestRun {
public static void main(String[] args) throws InterruptedException {
Object lock = new Object();
RequestAdmin requestAdmin = new RequestAdmin(lock);
RequestAdmin requestAdmin2 = new RequestAdmin(lock);
requestAdmin.start();
requestAdmin2.start();
}
}
start wait time: 1489730791034
start wait time: 1489730791068

我们看两个线程都暂停了,这就说明两个线程都获得了执行,原因就是上面分析的一样,wait()方法在执行完会立即释放对象的锁,所以线程一执行完时,线程二就可以直接获取到锁并执行,所以输出是异步显示的。下面我们在看一下notify()方法的事例。

/**
* 用户请求
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-15 10:44
* @since 1.0.0
*/
public class RequestUser extends Thread {


private Object lock;

public RequestUser(Object lock) {
this.lock = lock;
}

@Override
public void run() {
synchronized (lock) {
System.out.println(String.format("start notify time: %s", System.currentTimeMillis()));
lock.notify();
System.out.println(String.format("end notify: %s", System.currentTimeMillis()));
}
}
}
/**
* 测试类
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-15 10:49
* @since 1.0.0
*/
public class RequestRun {
public static void main(String[] args) throws InterruptedException {
Object lock = new Object();
RequestUser requestUser = new RequestUser(lock);
RequestUser requestUser2 = new RequestUser(lock);
requestUser.start();
requestUser2.start();
}
}
start notify time: 1489731048739
end notify: 1489731048790
start notify time: 1489731048790
end notify: 1489731048790

我们看线程是同步执行的。原因是notify()方法在执行后不会立刻释放对象的锁,所以线程一在执行notify()方法后,线程二虽然已经启动成功,但它获取不到当前对象的锁,因为线程一还没有将锁释放,所以线程二只能等待因为方法是synchronized同步方法,所以输出信息是同步执行的。


/**
* 管理用户请求
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-15 10:44
* @since 1.0.0
*/
public class RequestAdmin extends Thread {

private Object lock;

public RequestAdmin(Object lock) {
this.lock = lock;
}

@Override
public void run() {
try {
synchronized (lock) {
System.out.println(String.format("start wait time: %s\tthread: %s", System.currentTimeMillis(), Thread.currentThread().getName()));
lock.wait();
System.out.println(String.format("end wait: %s\tthread: %s", System.currentTimeMillis(), Thread.currentThread().getName()));
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* 用户请求
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-15 10:44
* @since 1.0.0
*/
public class RequestUser extends Thread {


private Object lock;

public RequestUser(Object lock) {
this.lock = lock;
}

@Override
public void run() {
synchronized (lock) {
System.out.println(String.format("start notify time: %s\tthread: %s", System.currentTimeMillis(), Thread.currentThread().getName()));
lock.notify();
System.out.println(String.format("end notify: %s\tthread: %s", System.currentTimeMillis(), Thread.currentThread().getName()));
}
}
}
/**
* 测试类
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-15 10:49
* @since 1.0.0
*/
public class RequestRun {
public static void main(String[] args) throws InterruptedException {
Object lock = new Object();
RequestAdmin requestAdmin = new RequestAdmin(lock);
RequestAdmin requestAdmin2 = new RequestAdmin(lock);
RequestAdmin requestAdmin3 = new RequestAdmin(lock);
RequestUser requestUser = new RequestUser(lock);
requestAdmin.start();
requestAdmin2.start();
requestAdmin3.start();
Thread.sleep(1000);
requestUser.start();
}
}
start wait time: 1489732406580	thread: Thread-0
start wait time: 1489732406621	thread: Thread-2
start wait time: 1489732406622	thread: Thread-1
start notify time: 1489732407594	thread: Thread-3
end notify: 1489732407594	thread: Thread-3
end wait: 1489732407594	thread: Thread-0

我们看线程一已经被唤醒了,然后继续执行了synchronized同步方法里的内容。

121212.jpg

线程状态图