方法wait()的作用是让当前执行代码的线程进行等待,wait()方法是object类的方法,该方法用来将当前的线程置入“预执行队列”中,并且在wait()所在的代码行处停止执行,直到接到通知或者被中断为止。在调用wait()之前,线程必须获得该对象的对象级别锁,即只能在同步方法或者同步块中调用wait()方法。在执行wait()方法后,当前线程释放锁。在从wait()返回前,线程与其他线程竞争重新获得锁。
notify()方法也要在同步方法或者同步块中调用,在调用前,线程也要活得对象的对象级别锁。在执行notify()方法后,当前线程不会马上释放对象锁,wait状态的线程也不会马上活得对象锁,要等notify线程中synchronized代码块执行完后,才释放锁。
import java.util.ArrayList;
import java.util.List;
public class MyObject {
private static List list = new ArrayList();
public static void add() {
list.add("1");
}
public static int size() {
return list.size();
}
}
public class MythreadA extends Thread{
private Object lock;
public MythreadA(Object lock) {
super();
this.lock = lock;
}
@Override
public void run(){
synchronized (lock) {
if (MyObject.size() != 5) {
try {
System.out.println("wait begin");
// 必须使用在被synchronized同步的object的临界区内。
lock.wait();//释放锁
System.out.println("wait end");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public class MythreadB extends Thread{
private Object lock;
public MythreadB(Object lock) {
super();
this.lock = lock;
}
@Override
public void run(){
synchronized (lock) {
for (int i = 0; i < 10; i++) {
MyObject.add();
if (MyObject.size() == 5) {
lock.notify();
System.out.println("already send notify");
}
System.out.println("add" + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public class Main {
public static void main(String[] args) {
try {
MyObject object = new MyObject();
MythreadA a = new MythreadA(object);
a.setName("A");
MythreadB b = new MythreadB(object);
b.setName("B");
a.start();
b.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
wait end在最后输出,说明notify方法执行后不立即释放锁。
notifyAll方法可以所有wait唤醒。
wait(long timeout)方法可以传入参数,如果在timeout时间内未被唤醒,则他会自动唤醒。
Join方法
在主线程创建并启动子线程,如果主线程需要等待子线程执行完后悔再结束,需要用到join方法,join方法就是等待线程对象销毁。
public class MythreadA extends Thread{
private Object lock;
public MythreadA(Object lock) {
super();
this.lock = lock;
}
@Override
public void run(){
synchronized (lock) {
try {
Thread.sleep(10000);
System.out.println("10s pass");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Main {
public static void main(String[] args) {
try {
MyObject object = new MyObject();
MythreadA a = new MythreadA(object);
a.setName("A");
a.start();
a.join();
System.out.println("A 已经执行完");
} catch (Exception e) {
e.printStackTrace();
}
}
}
与wait类似,join(long timeout)方法可以设定等待的时间。
Join和sleep的方法的区别在于
sleep(long)方法在睡眠时不释放对象锁
join(long)方法在等待的过程中释放对象锁
public class ThreadA extends Thread {
private ThreadB b;
public ThreadA(ThreadB b) {
super();
this.b = b;
}
@Override
public void run() {
try {
synchronized (b) {
b.start();
b.join();//释放b锁
for (int i = 0; i < Integer.MAX_VALUE; i++) {
String newString = new String();
Math.random();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}