sleep()
public class Demo2 {
private static final String lock = new String("lock");
public static void main(String[] args) {
myThread();
myThread();
}
private static void myThread() {
new Thread(() -> {
System.out.println(System.currentTimeMillis() + Thread.currentThread().getName() + "正在运行");
synchronized (lock) {
try {
System.out.println(System.currentTimeMillis() + Thread.currentThread().getName() + "获取到锁");
System.out.println(System.currentTimeMillis() + Thread.currentThread().getName() + "sleep");
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(System.currentTimeMillis() + Thread.currentThread().getName() + "运行结束");
}
}).start();
}
}
执行结果:
1655345999323Thread-0正在运行
1655345999323Thread-1正在运行
1655345999331Thread-0获取到锁
1655345999331Thread-0sleep
1655346009336Thread-0运行结束
1655346009338Thread-1获取到锁
1655346009338Thread-1sleep
1655346019343Thread-1运行结束
总结:
- sleep()是Thread的静态方法;
- 从执行结果看,在线程0调用 sleep() 后,线程1并没有获取到锁。而是等线程0运行结束后,才获取到锁。说明线程调用 sleep() 后,是不会释放锁的。
wait()
指定等待的时间,到期后自动被唤醒
package com.learn.blog.demo;
public class Demo3 {
private static final String lock = new String("lock");
public static void main(String[] args) {
myThread();
myThread();
}
private static void myThread() {
new Thread(() -> {
System.out.println(System.currentTimeMillis() + Thread.currentThread().getName() + "正在运行");
synchronized (lock) {
try {
System.out.println(System.currentTimeMillis() + Thread.currentThread().getName() + "获取到锁");
System.out.println(System.currentTimeMillis() + Thread.currentThread().getName() + "wait");
lock.wait(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(System.currentTimeMillis() + Thread.currentThread().getName() + "运行结束");
}
}).start();
}
}
执行结果:
1655346407235Thread-1正在运行
1655346407235Thread-0正在运行
1655346407243Thread-1获取到锁
1655346407243Thread-1wait
1655346407243Thread-0获取到锁
1655346407244Thread-0wait
1655346408249Thread-1运行结束
1655346408249Thread-0运行结束
总结:
- wait()是Ojbect的静态方法;
- wait()可以指定等待时长,到期后自动被唤醒;
- 从执行结果看,在线程1调用 wait() 后,线程0马上就获取到锁,并不需要等到线程1执行结束。说明线程调用 wait() 后,会释放锁。
不指定等待时长,需要手动notify/notifyAll唤醒
package com.learn.blog.demo;
public class Demo4 {
private static final String lock = new String("lock");
public static void main(String[] args) {
myThread();
myThread();
}
private static void myThread() {
new Thread(() -> {
System.out.println(System.currentTimeMillis() + Thread.currentThread().getName() + "正在运行");
synchronized (lock) {
try {
lock.notify();
System.out.println(System.currentTimeMillis() + Thread.currentThread().getName() + "获取到锁");
System.out.println(System.currentTimeMillis() + Thread.currentThread().getName() + "wait");
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(System.currentTimeMillis() + Thread.currentThread().getName() + "运行结束");
}
}).start();
}
}
执行结果:
1655347146777Thread-0正在运行
1655347146777Thread-1正在运行
1655347146785Thread-0获取到锁
1655347146785Thread-0wait
1655347146785Thread-1获取到锁
1655347146785Thread-1wait
1655347146785Thread-0运行结束
总结:
从执行结果看,在线程0调用 wait 后,线程1获取到锁,调用notify唤醒了线程0,然后自己进入wait。此时,线程0获取到锁,线程0执行结束。线程1依然处于等待状态,没有线程唤醒它,所以线程1一直没有执行结束。
join()
package com.learn.blog.demo;
public class Demo5 {
public static void main(String[] args) throws InterruptedException {
System.out.println("主线程执行开始");
Thread thread = new Thread(() -> {
System.out.println("join线程执行开始");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("join线程执行结束");
});
thread.start();
thread.join();
System.out.println("主线程执行结束");
}
}
执行结果:
主线程执行开始
join线程执行开始
join线程执行结束
主线程执行结束
总结:
join()执行后线程进入阻塞状态,例如线程A中调用线程B的join(),那么线程A会进入到阻塞队列,直到线程B结束。
sleep、wait和join的总结
sleep()和wait()对比
- sleep()是Thread的静态本地方法,wait()是Object的静态本地方法
- sleep()不会释放lock,wait()会释放lock
- sleep()不需要被唤醒,wait()需要(不指定等待时长的情况)
join()执行后线程进入阻塞状态,例如线程A中调用线程B的join(),那么线程A会进入到阻塞队列,直到线程B结束