使用了wait方法之后,线程就会进入阻塞阶段,只有发生以下四种情况中的其中一个,线程才会被唤醒
notify会唤醒单个处于阻塞状态的线程,唤醒的线程是随机的
notify和wait都需要写在synchronized代码块里,不然会抛出异常
notifyAll会唤醒所有等待的线程
执行wait方法之后,被中断,会抛出InterruptedException这个异常
public class Wait {
public static void main(String[] args) throws InterruptedException {
Thread1 thread1 = new Thread1();
Thread2 thread2 = new Thread2();
thread1.start();
Thread.sleep(200);
thread2.start();
}
public static Object object = new Object();
static class Thread1 extends Thread {
@Override
public void run() {
synchronized (object) {
System.out.println("Thread1执行");
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread1获取锁");
}
}
}
static class Thread2 extends Thread {
@Override
public void run() {
synchronized (object) {
object.notify();
System.out.println("Thread2调用notify");
}
}
}
}
/*
Thread1执行
Thread2调用notify
Thread1获取锁
* */
public class notifyOrAll implements Runnable{
private static final Object a = new Object();
public static void main(String[] args) throws InterruptedException {
Runnable r = new notifyOrAll();
Thread threada = new Thread(r);
Thread threadb = new Thread(r);
Thread threadc = new Thread(new Runnable() {
@Override
public void run() {
synchronized (a) {
// a.notifyAll();
a.notify();
System.out.println(Thread.currentThread().getName() + "notify");
}
}
});
threada.start();
Thread.sleep(200);
threadb.start();
Thread.sleep(200);
threadc.start();
}
@Override
public void run() {
synchronized (a) {
System.out.println(Thread.currentThread().getName() + "得到锁");
try {
System.out.println(Thread.currentThread().getName() + "wait");
a.wait();
System.out.println(Thread.currentThread().getName() + "wait结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/*
Thread-0得到锁
Thread-0wait
Thread-1得到锁
Thread-1wait
Thread-2notifyAll
Thread-1wait结束
Thread-0wait结束
* */
/*
Thread-0得到锁
Thread-0wait
Thread-1得到锁
Thread-1wait
Thread-2notify
Thread-0wait结束
* */
public class OwnMonitor {
private static volatile Object a = new Object();
private static volatile Object b = new Object();
public static void main(String[] args) throws InterruptedException {
Thread threadA = new Thread(new Runnable() {
@Override
public void run() {
synchronized (a) {
System.out.println("threadA得到a");
synchronized (b) {
System.out.println("threadA得到锁b");
try {
System.out.println("threadA释放a");
a.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
});
Thread threadB = new Thread(new Runnable() {
@Override
public void run() {
synchronized (a) {
System.out.println("threadB得到a");
System.out.println("threadB要获取b");
synchronized (b) {
System.out.println("threadB得到b");
}
}
}
});
threadA.start();
Thread.sleep(1000);
threadB.start();
}
}
/*
threadA得到a
threadA得到锁b
threadA释放a
threadB得到a
threadB要获取b
* */
当线程从wait状态刚被唤醒时,通常不能直接得到锁,那就会从waiting状态转换到blocked状态,抢到锁之后状态转变为runnable
如果发生异常,则直接跳到Terminated状态
public class ProducerConsumer {
public static void main(String[] args) {
Storge storge = new Storge();
Producer producer = new Producer(storge);
Consumer consumer = new Consumer(storge);
new Thread(producer).start();
new Thread(consumer).start();
}
}
class Producer implements Runnable {
private Storge storge;
public Producer(Storge storge) {
this.storge = storge;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
storge.put();
}
}
}
class Consumer implements Runnable {
private Storge storge;
public Consumer(Storge storge) {
this.storge = storge;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
storge.take();
}
}
}
class Storge {
private int maxSize;
private LinkedList<Date> storge;
public Storge() {
maxSize = 10;
storge = new LinkedList<>();
}
public synchronized void put() {
while (storge.size() == maxSize) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
storge.add(new Date());
System.out.println("已经有了" + storge.size());
notify();
}
public synchronized void take() {
while (storge.size() == 0) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("拿到了" + storge.poll() + "还剩" + storge.size());
notify();
}
}
作用:让线程在预期的时间执行,其他时间不占用CPU资源
特点:和wait不一样,sleep不释放锁
public class SleepSyn implements Runnable{
public static void main(String[] args) {
SleepSyn sleepSyn = new SleepSyn();
new Thread(sleepSyn).start();
new Thread(sleepSyn).start();
}
@Override
public void run() {
syn();
}
private synchronized void syn() {
System.out.println(Thread.currentThread().getName() + "获取锁");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "释放锁");
}
}
/*
* Thread-0获取锁
Thread-0释放锁
Thread-1获取锁
Thread-1释放锁
* */
证明sleep不释放Lock锁
public class sleepLock implements Runnable{
private static final Lock LOCK = new ReentrantLock();
@Override
public void run() {
LOCK.lock();
System.out.println(Thread.currentThread().getName() + "获取锁");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
LOCK.unlock();
}
System.out.println(Thread.currentThread().getName() + "释放锁");
}
public static void main(String[] args) {
sleepLock sleepLock = new sleepLock();
new Thread(sleepLock).start();
new Thread(sleepLock).start();
}
}
/*
* Thread-0获取锁
Thread-0释放锁
Thread-1获取锁
Thread-1释放锁
* */
public class sleepInterrupted implements Runnable{
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new sleepInterrupted());
thread.start();
Thread.sleep(2000);
thread.interrupt();
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(new Date());
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
System.out.println("中断");
e.printStackTrace();
}
}
}
}
/*
* Fri Jan 27 21:11:57 CST 2023
Fri Jan 27 21:11:58 CST 2023
中断
Fri Jan 27 21:11:59 CST 2023
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:340)
at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
at com.jx.JavaTest.ThreadObjectMethod.sleepInterrupted.run(sleepInterrupted.java:21)
at java.lang.Thread.run(Thread.java:748)
Fri Jan 27 21:12:00 CST 2023
Fri Jan 27 21:12:01 CST 2023
Fri Jan 27 21:12:02 CST 2023
Fri Jan 27 21:12:03 CST 2023
Fri Jan 27 21:12:04 CST 2023
Fri Jan 27 21:12:05 CST 2023
Fri Jan 27 21:12:06 CST 2023
Process finished with exit code 0
* */
sleep方法可以让线程进入waiting状态,不占用CPU资源,但是不释放锁,规定时间之后再运行
休眠期间如果被打断,会抛出异常并清除中断状态
新线程加入,主线程等子线程执行完毕
public class join {
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "执行完毕");
}
});
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "执行完毕");
}
});
thread1.start();
thread2.start();
System.out.println("开始等待子线程运行");
// thread1.join();
// thread2.join();
System.out.println("所有线程执行完毕");
}
}
/*
* 开始等待子线程运行
Thread-0执行完毕
Thread-1执行完毕
所有线程执行完毕
* */
/*
* 开始等待子线程运行
所有线程执行完毕
Thread-1执行完毕
Thread-0执行完毕
* */
public class joinInterrupt {
public static void main(String[] args) {
Thread main1 = Thread.currentThread();
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
try {
main1.interrupt();
Thread.sleep(2000);
System.out.println("启动");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread1.start();
System.out.println("join");
try {
thread1.join();
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName() + "中断");
// thread1.interrupt();
e.printStackTrace();
}
System.out.println("子线程运行完毕");
}
}
/*
* join
启动
子线程运行完毕
* */
/*
* join
main中断
子线程运行完毕
java.lang.InterruptedException
at java.lang.Object.wait(Native Method)
at java.lang.Thread.join(Thread.java:1252)
at java.lang.Thread.join(Thread.java:1326)
at com.jx.JavaTest.ThreadObjectMethod.joinInterrupt.main(joinInterrupt.java:23)
启动
Process finished with exit code 0
* */
/*
* join
main中断
子线程运行完毕
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at com.jx.JavaTest.ThreadObjectMethod.joinInterrupt$1.run(joinInterrupt.java:13)
at java.lang.Thread.run(Thread.java:748)
java.lang.InterruptedException
at java.lang.Object.wait(Native Method)
at java.lang.Thread.join(Thread.java:1252)
at java.lang.Thread.join(Thread.java:1326)
at com.jx.JavaTest.ThreadObjectMethod.joinInterrupt.main(joinInterrupt.java:23)
Process finished with exit code 0
* */
join期间,线程处于WAITING状态
public class joinStates {
public static void main(String[] args) throws InterruptedException {
Thread main1 = Thread.currentThread();
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
System.out.println(main1.getState());
System.out.println("子线程运行结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread.start();
System.out.println("join");
thread.join();
System.out.println("运行完毕");
}
}
/*
* join
WAITING
子线程运行结束
运行完毕
* */
用来释放CPU时间片,但是不一定能达到预期的效果,因为有时CPU资源不紧张,无需yield
和sleep的区别是:sleep期间不会被再次调度但是yield会立刻处于竞争状态,还会随时再次被调度