join();—->Thread类
让多个线程同步执行 变成单个线程
join()方法底层其实是调用了wait()方法
1.有两个线程 one two two加到one里
2.设计模型的时候 将two线程在one的run方法里创建 保证两个有先后顺序
3.two.join();无参数 —-> join(0); 有参数 —-> join(long millis);—->
if (millis == 0) {//即 join(0);
while (isAlive()) { //没人调用方法就相当于this.isAlive() 即two对象调 如果two活着
wait(0); //this.wait(0)—->让别人等着 即访问two对象的线程进入等待状态 即one
}
}
4. one对象只有两个时间点访问到two对象
1 two想要join的时候
2 two执行完毕 或 join(millis)中等待的时间到的时候
线程one:
public class ThreadOne extends Thread{
public void run(){
System.out.println("ThreadOne 执行了");
ThreadTwo two = new ThreadTwo();
two.start();
try {
two.join(2000);//线程2加到线程1中
//join();不带参数的相当于调的是join(long); 即join(0);
//join(2000)即表明one给two的执行时间 若执行比我们的时间长 one会把two踢走 自己继续执行
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("ThreadOne 结束了");
}
}
线程two:
public class ThreadTwo extends Thread{
public void run(){
System.out.println("two 执行了");
ThreadThree three = new ThreadThree(this);//this就是当前调用run方法的那个two对象
//传进去的two对象就能保证three的run方法锁的是这个two对象
three.start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("two 结束了");
}
}
线程three:
public class ThreadThree extends Thread{
//这里是为了能在run方法中把join到one里执行的那个two对象锁起来
//但是又不能在run方法里new一个two对象 这样就不是同一个two对象了
//而且run方法是重写的 不能传参
//所以只能加属性
private ThreadTwo two;
//调用three的构造方法时 two就有了
public ThreadThree(ThreadTwo two){
this.two = two;
}
public void run(){
System.out.println("three 执行了");
//在two执行的过程中 one等待时 three把two对象锁起来
synchronized (two) {//把线程2锁住了
//即one对象想把two对象踢走时 发现two对象被锁定了 那么one对象只能等待three把two释放
System.out.println("two 被锁了");
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("two自由了");
}
System.out.println("three 执行完毕");
}
}
主方法:
public static void main(String[] args){
ThreadOne one = new ThreadOne();
one.start();
}