
必须要获取到锁对象, 才能调用这些方法

下面的三个方法都是Object中的方法; 通过锁对象来调用
不同点
同点
为什么 if会出现虚假唤醒?
使用while循环去循环判断一个条件,而不是使用if只判断一次条件;即wait()要在while循环中
public class SpuriousWakeup {
public static void main(String[] args) {
WareHouse wareHouse = new WareHouse();
Producer producer = new Producer(wareHouse);
Customer customer = new Customer(wareHouse);
new Thread(producer, "ProducerA").start();
new Thread(producer, "ProducerB").start();
new Thread(customer, "ConsumerC").start();
new Thread(customer, "ConsumerD").start();
}
}
// 仓库
class WareHouse {
private volatile int product = 0;
// 入库
public synchronized void purchase() {
// 库存已满,仓库最多容纳1个货品
while (product > 0) {
System.out.println(Thread.currentThread().getName() + ": " + "已满!");
try {
this.wait();
} catch (InterruptedException e) {
// ignore exception
}
}
++product;
// 该线程从while中出来的时候,已满足条件
System.out.println(Thread.currentThread().getName() + ": " + "-------------入库成功,余货:" + product);
this.notifyAll();
}
// 出库
public synchronized void outbound() {
while (product <= 0) {
System.out.println(Thread.currentThread().getName() + ": " + "库存不足,无法出库");
try {
this.wait();
} catch (InterruptedException e) {
// ignore exception
}
}
--product;
System.out.println(Thread.currentThread().getName() + ":出库成功,余货:" + product);
this.notifyAll();
}
}
// 生产者
class Producer implements Runnable {
private WareHouse wareHouse;
public Producer(WareHouse wareHouse) {
this.wareHouse = wareHouse;
}
@Override
public void run() {
for (int i = 0; i < 5; ++i) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
}
wareHouse.purchase();
}
}
}
// 消费者
class Customer implements Runnable {
private WareHouse wareHouse;
public Customer(WareHouse wareHouse) {
this.wareHouse = wareHouse;
}
@Override
public void run() {
for (int i = 0; i < 5; ++i) {
wareHouse.outbound();
}
}
}输出结果:

示例
先打印t1,1s后打印mian
public class TestJoin {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
System.out.println("t1");//先执行
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "t1");
t1.start();
t1.join();
System.out.println("main");//一秒后执行
}
}join()
join(long)
public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();//起始时间
long now = 0;//已经暂停时间
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}public final native void wait(long timeout) throws InterruptedException;// 暂停当前线程
LockSupport.park();
// 恢复某个线程的运行
LockSupport.unpark(thread);每个线程都有自己的一个 Parker 对象,由三部分组成 _counter, _cond和 _mutex
先调用park再调用upark的过程
先调用park的情况

调用unpark

先调用upark再调用park的过程



1、 NEW <–> RUNNABLE
2、RUNNABLE <–> WAITING
3、RUNNABLE <–> WAITING
4、RUNNABLE <–> WAITING
5、RUNNABLE <–> TIMED_WAITING (带超时时间的wait)
6、RUNNABLE <–> TIMED_WAITING
7、RUNNABLE <–> TIMED_WAITING
8、RUNNABLE <–> TIMED_WAITING
9、RUNNABLE <–> BLOCKED
10、 RUNNABLE <–> TERMINATED