![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/1ecf87f8bfa48fed510fc7765734251b.png)
sleep VS wait
sleep()方法(休眠)是线程类(Thread)的静态方法,调用此方法会让当前线程暂停执行指定的时间,将执行机会(CPU)让给其他线程,但是对象的锁依然保持,因此休眠时间结束后会自动恢复(线程回到就绪状态,请参考第66题中的线程状态转换图)。
.
wait()是Object类的方法,调用对象的wait()方法导致当前线程放弃对象的锁(线程暂停执行),进入对象的等待池(wait pool),只有调用对象的notify()方法(或notifyAll()方法)时才能唤醒等待池中的线程进入等锁池(lock pool),如果线程重新获得对象的锁就可以进入就绪状态。
请说出与线程同步以及线程调度相关的方法。
wait():使一个线程处于等待(阻塞)状态,并且释放所持有的对象的锁;
.
sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要处理InterruptedException异常;
.
notify():唤醒一个处于等待状态的线程,当然在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且与优先级无关;
.
notityAll():唤醒所有处于等待状态的线程,该方法并不是将对象的锁给所有线程,而是让它们竞争,只有获得锁的线程才能进入就绪状态。
.
Thread.yield 让出CPU,进入就绪状态
.
t1.join() 阻塞宿主线程
1.join()方法
public class ThreadJoinTest {
/**
* Join(): 又叫做:等待线程死亡(Waits for this thread to die.)
*
* 测试case说明:
* join()方法只会使宿主线程(或者说调用t.join()的线程)进入等待池并等待t线程执行完毕后才会被唤醒。并不影响同一时刻处在运行状态的其他线程。
* join源码中,只会调用wait方法,并没有在结束时调用notify,这是因为线程在die的时候会自动调用自身的notifyAll方法,来释放所有的资源和锁。
* 需要注意,如果ta线程未被启动或者终止,则isAlive方法返回false,及join方法无效
*
*/
public static void main(String[] args) throws InterruptedException {
ThreadTestP1 ta = new ThreadTestP1("A");
ThreadTestP1 tb = new ThreadTestP1("B");
ThreadTestP1 tc = new ThreadTestP1("C");
//启动线程
ta.start();
System.out.println("-----------AAA------------------------------------");
tb.start();
System.out.println("-----------BBB-----------------------------------");
ta.join();
tc.start();
// Thread.sleep(3000);
}
}
-----------------------------------------------------------------
@Slf4j
@Data
@AllArgsConstructor
public class ThreadTestP1 extends Thread {
private String tName;
@SneakyThrows
@Override
public void run() {
for (int i = 1; i <= 5; i++) {
Thread.sleep(100);
log.info("ThreadTestP1 name is {}, iter:[{}]",tName,i);
}
}
}
-----------------------------源码------------------------------------------
/**
* millis 设置超时时间
* 关键点: synchronized,
* join方法的本质调用的是Object中的wait方法实现线程的阻塞。
* 但是我们需要知道的是,调用wait方法必须要获取锁,所以join方法是被synchronized修饰的
* synchronized修饰在方法层面相当于synchronized(this),this就是Thread本身的实例
*/
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");
}
// 判断是否携带阻塞的超时时间,等于0表示没有设置超时时间
if (millis == 0) {
while (isAlive()) {
wait(0); // ---> 无限等待直到线程t结束
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay); // ---> 等待指定的时间后,宿主线程阻塞结束
now = System.currentTimeMillis() - base;
}
}
}