多线程学习—1-wait(),notify(),notifyAll()

前言

​ 最近准备把多线程的知识重新过一遍,决定从基础写起。这篇主要讲的是多线程的wait(),notify(),notifyAll()方法。

这三个方法都属于类方法,Object类都会有这三个方法,wait()是暂时让出给其他线程,而当前线程会一直阻塞直到等到notify(All)通知或者中断,而notify()和notifyAll()则是通知持有该锁的对象”等待获取该对象的对象锁”,因此必须要写在同步代码块内,至于为什么notify()和notifyAll()是通知”等待”,下面会详细解释。

wait

​ wait()的作用是使当前执行代码的线程进行等待,将当前线程置入”预执行队列”中,并且wait()所在的代码处停止执行,直到接到通知或被中断。在调用wait()之前,线程必须获得该对象的锁,因此只能在同步方法/同步代码块中调用wait()方法

notify(All)

​ notify()的作用是,如果有多个线程等待,那么线程规划器随机挑选出一个wait的线程,对其发出通知notify(),并使它等待获取该对象的对象锁。注意”等待获取该对象的对象锁”,这意味着,即使收到了通知,wait的线程也不会马上获取对象锁,必须等待notify()方法的线程释放锁才可以。和wait()一样,notify()也要在同步方法/同步代码块中调用

总结起来就是,wait()使线程停止运行,notify()使停止运行的线程继续运行

代码

​ 上面关于wait和notify的总结是前辈写的,下面给出我自己的示例。请大家根据注释,适当的去掉注释看看结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package MyThread;
/**
* Created by yuhang on 2016/11/30.
*/
public class MyThread1 extends Thread {
Object lock = new Object();
public MyThread1(Object lock) {
System.out.println("Constructor method->>CurrentThreadName: " + Thread.currentThread().getName());
System.out.println("Constructor method->>this.threadName: " + this.getName());
System.out.println("**********************************************");
this.lock = lock;
}
@Override
public void run() {
synchronized (this.lock) {
System.out.println("Run method->>CurrentThreadName: " + Thread.currentThread().getName());
System.out.println("Run method->>this.threadName: " + this.getName());
try {
System.out.println("MyThread1:" + Thread.currentThread().getName() + " get the lock,and i will wait for some notify!");
long statrTime = System.currentTimeMillis();
//wait是让使用wait方法的对象等待,暂时先把对象锁给让出来,给其它持有该锁的对象用,其它对象用完后再告知(notify)等待的那个对象可以继续执行了
this.lock.wait();
System.out.println("MyThread1" + Thread.currentThread().getName() + " wait end! lock time : " + (System.currentTimeMillis() - statrTime) / 1000);
} catch (InterruptedException e) {
System.out.println("wait be interrupted by interrupt method just now!");
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Object lock = new Object();
MyThread1 myThread1 = new MyThread1(lock);
MyThread1 myThread2 = new MyThread1(lock);
myThread1.start();
myThread2.start();
//wait和notify必须要写在同步代码块内部 否则会报java.lang.IllegalMonitorStateException异常
synchronized (lock) {
try {
Thread.sleep(3000);
lock.notifyAll();
//lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package MyThread;
/**
* Created by yuhang on 2016/11/30.
*/
public class MyThread2 extends Thread {
Object lock = new Object();
public MyThread2(Object lock) {
this.lock = lock;
}
@Override
public void run() {
synchronized (lock) {
System.out.println(Thread.currentThread().getName() + "will notify!");
//notify不会马上释放锁,会等到当前同步代码块执行完,才会释放锁
lock.notify();
System.out.println(Thread.currentThread().getName() + " notified ,but didn't release!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " after sleep,will release the lock!");
}
}
public static void main(String[] args) {
Object lock = new Object();
MyThread1 myThread1 = new MyThread1(lock);
myThread1.start();
//测试Notify不释放锁
MyThread2 myThread2 = new MyThread2(lock);
//myThread2.start();
//测试interrupt方法
// try {
// Thread.sleep(10000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// System.out.println(myThread1.getName() + "will execute interrupt method!");
// myThread1.interrupt();
try {
//join方法会释放锁,但是不加时间会一直阻塞当前执行的线程直到myThead1的run方法执行完成
myThread1.join();//.join(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//如果没有Join方法myThead2线程是不会启动的
myThread2.start();
System.out.println("i will print after myThead1 complete!");
}
}
坚持原创技术分享,您的支持将鼓励我继续创作!

热评文章