Join方法
一.概念及作用
join方法四用于在一个线程中,调用其他线程的join方法,则此线程等待其他线程完成任务.
二.特点
1.是Thread类的方法,故只能是线程及其子类调用.
2.底层调用的是object的wait方法.
3.Join()方法会释放锁,但是只能释放它join的对象的锁.
三.代码
功能就是,首先主线程先输出到10;然后等待子线程输出到10;最后主线程再输出剩余的
情况0:主线程或只线程,至少有一方不是同步方法
子线程类
class MyThread extends Thread{
public Object o;
public MyThread(Object o) {
this.o = o;
}
@Override
public void run() {
synchronized (this) { //子线程加锁
for(int i = 0; i < 10; i ++) {
System.out.println("Mythread----" + i);
}
}
}
}
主线程类
public class TestJoin {
public static void main(String[] args) throws Exception {
Object o = new Object();
//子线程,加锁对象也是对象o
MyThread mt = new MyThread(o);
mt.start();
for(int i = 0 ; i < 20; i ++) {
System.out.println("main----" + i);
if(i == 10) {
mt.join(); //主线程等待对象,即释放锁的对象为mt
}
}
}
}
运行结果:1.主线程和子线程一起,但是当主线程到11的时候必须等待子线程先完成.
情况一:主线程和子线程,使用不同的锁.
子线程类
class MyThread extends Thread{
public Object o;
public MyThread(Object o) {
this.o = o;
}
@Override
public void run() {
synchronized (o) { //子线程申请o对象锁
for(int i = 0; i < 10; i ++) {
System.out.println("Mythread----" + i);
}
}
}
}
主线程
public class TestJoin {
public static void main(String[] args) throws Exception {
Object o = new Object();
//子线程,加锁对象也是对象o
MyThread mt = new MyThread(o);
mt.start();
synchronized (TestJoin.class) {//主线程加锁对象其他对象
for(int i = 0 ; i < 20; i ++) {
System.out.println("main----" + i);
if(i == 10) {
mt.join(); //主线程等待对象,即释放锁的对象为mt
}
}
}
}
}
运行结果:结果是主子线程各自运行各自的.
情况2:主线程和子线程,使用相同的锁,但是锁住的这个对象不是join对象
子线程类
class MyThread extends Thread{
public Object o;
public MyThread(Object o) {
this.o = o;
}
@Override
public void run() {
synchronized (o) { //锁住的是对象o
for(int i = 0; i < 10; i ++) {
System.out.println("Mythread----" + i);
}
}
}
}
主线程类
public class TestJoin {
public static void main(String[] args) throws Exception {
Object o = new Object();
//子线程,加锁对象也是对象o
MyThread mt = new MyThread(o);
mt.start();
synchronized (o) {//主线程加锁对象也是对象o
for(int i = 0 ; i < 20; i ++) {
System.out.println("main----" + i);
if(i == 10) {
mt.join(); //主线程等待对象,即释放锁的对象为mt
}
}
}
}
}
运行结果:主线程进入等待死循环,且没有释放o对象锁.
情况3:主线程和子线程,使用相同的锁,锁住的就是join的子线程对象
子线程类
class MyThread extends Thread{
public Object o;
public MyThread(Object o) {
this.o = o;
}
@Override
public void run() {
synchronized (this) { //锁住的就是本对象
for(int i = 0; i < 10; i ++) {
System.out.println("Mythread----" + i);
}
}
}
}
主线程类
public class TestJoin {
public static void main(String[] args) throws Exception {
Object o = new Object();
//子线程,加锁对象也是对象o
MyThread mt = new MyThread(o);
mt.start();
synchronized (mt) {//主线程加锁对象就是join的线程对象
for(int i = 0 ; i < 20; i ++) {
System.out.println("main----" + i);
if(i == 10) {
mt.join(); //主线程等待对象,即释放锁的对象为mt
}
}
}
}
}
运行结果:主线程(0-10)>子线程(0-9)>主线程
四.使用场景总结
使用场景:
join一般应用于两个线程之间的执行顺序,不擅长于控制多个程序之间的排序控制,常用于主线程等待子线程返回结果.如果期望多个线程之间的排序,可参考CountDownLaunch等.
使用注意事项:
1.一定是main线程中调用等待的线程的join()方法
2.如果主线程和子线程都是同步方法,则需要子线程加锁对象为this,主线程加锁对象为join的线程…这样才能释放锁.
3.join()方法会释放锁,但是只会释放join的线程对象的锁.