1. join() 方法
join() 方法可以理解为一种插队现象。即线程A执行了线程B的join方法,线程A 必须等待线程B执行完成以后,才能继续往下执行。
业务需求:我们现在new出10个线程,让主线程插队,最先开始执行。剩下的线程也依次按序号插队执行。
代码:
JumpQueue()的参数是传入插队的线程,那么0号线程执行main.join(), 1号线程执行0.join(), 依次类推,所以最先执行完的是main线程。然后依次是0,1,2…9
package join的用法;
public class UseJoin {
static class JumpQueue implements Runnable{
private Thread thread; //用来插队的线程
public JumpQueue(Thread thread) {
this.thread = thread;
}
@Override
public void run() {
try{
//插队执行
thread.join();
}catch (Exception e){
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" terminate.");
}
}
//让线程依次插队执行
public static void main(String[] args) throws InterruptedException {
Thread previous = Thread.currentThread(); //现在是主线程
for (int i = 0; i < 10; i++) {
Thread thread =
new Thread(new JumpQueue(previous), String.valueOf(i));
System.out.println(previous.getName()+" jump a queue the thread:"
+thread.getName());
thread.start();
previous = thread;
}
Thread.sleep(2000); //让主线程休眠2s
System.out.println(Thread.currentThread().getName()+" terminate");
}
}

2.调用yield() ,sleep(), wait(), notify() 对锁有何影响

- 线程在执行sleep() 方法之后,是不会释放锁的,但它在指定的睡眠的时间内会进入阻塞状态,不会被CPU所调度。(不会释放锁意味着如果有 synchronized 同步块,其他线程仍然不能访问共享数据。)
- 线程在执行yield()方法之后,也是不会释放锁的,但它与sleep()不同,它不会进入阻塞状态,而是进入就绪状态。在下一个时间片轮转调度的情况下,CPU仍然可以调用到该方法。
- 线程在调用wait()方法之前必须持有锁,不然会抛出异常。当调用wait()方法后,会释放锁,直到有人调用了notify()或者notifyAll()的情况下它才可能重新持有锁。(除了使用 notify() 和 notifyAll() 方法外,还可以使用带毫秒参数的 wait(long timeout) 方法,效果是在延迟 timeout 毫秒后,可以重新持有锁。还有一点需要注意的是,即使timeout时间没走完,它仍然可以被notify()或notifyAll()方法唤醒)
- 线程在调用notify()或notifyAll() 方法之前,必须持有锁,不然也会抛出异常。但该方法调用之后本身是不会释放锁的,但因为调用方法都位于同步代码块中(Synchronized),所以执行完完整的方法自然会释放锁,所以在书写业务代码的时候,一般建议把notify()或者notifyAll() 放在同步代码块的最后执行。
本文详细介绍了Java中线程的调度方式,包括join()方法的使用,使线程按序执行,以及yield(), sleep(), wait(), notify()等方法对锁的影响。通过实例代码解释了如何控制线程的执行顺序,并探讨了这些方法在锁持有情况下的行为差异。

1187

被折叠的 条评论
为什么被折叠?



