多线程02——如何控制线程执行顺序

之前说过多线程的启动顺序不等于执行顺序,文章链接,但是我们可以使用代码控制线程的状态进而控制线程执行顺序。

这里使用join()方法:

API中那句“等待该线程终止”,主语是join方法被调用时所处的线程,“该线程”是指调用join方法的线程。

比如现在有a、b两个线程对象,在a线程中出现b.join(),那么a线程将会被阻塞(或者说挂起),直到b线程执行完毕才会继续执行b.join()语句下面的代码,即继续执行a线程。

澄清概念:join() 的作用不是让“主线程”等待“子线程”结束之后才能继续运行,而是哪个线程内出现join方法,哪个线程就会被挂起。

下面一共4个线程,其中含3个其它线程(或者叫子线程),我们的目的是先创建的子线程线程先执行完。

此时有两种方式,第一种是将主线程作为标准,每个线程依次阻塞主线程,代码如下:

public class MyThread1 extends Thread{
	@Override
	public void run() {
		System.out.println("继承Thread线程名称>>"+Thread.currentThread().getName());
		otherMethod();

	}
	public void otherMethod() {
		for(int i=10;i<=15;i++) {		
			System.out.println("继承Thread>>"+Thread.currentThread().getName()+":数值>>"+i);
		}
	}
}

public class MyThread2 extends Thread{
	@Override
	public void run() {
		System.out.println("继承Thread线程名称>>"+Thread.currentThread().getName());
		otherMethod();

	}
	public void otherMethod() {
		for(int i=20;i<=25;i++) {		
			System.out.println("继承Thread>>"+Thread.currentThread().getName()+":数值>>"+i);
		}
	}
}

public class MyThread3 extends Thread{
	@Override
	public void run() {
		System.out.println("继承Thread线程名称>>"+Thread.currentThread().getName());
		otherMethod();

	}
	public void otherMethod() {
		for(int i=30;i<=35;i++) {		
			System.out.println("继承Thread>>"+Thread.currentThread().getName()+":数值>>"+i);
		}
	}
}

public class Test {
	//主方法本身所在的是主线程
	public static void main(String[] args) {
		System.out.println("主线程名称>>"+Thread.currentThread().getName());
		//创建继承Thread类的多线程对象
		try {
			Thread thread1=new MyThread1();		
			Thread thread2=new MyThread2();		
			Thread thread3=new MyThread3();			
			//启动一个线程
			thread1.start();
			//在主线程中出现join方法,主线程被挂起,直至调用join方法的线程(thread1对象)执行完毕才会向下执行
			thread1.join();
			
			//启动一个线程
			thread2.start();
			thread2.join();
			
			//启动一个线程
			thread3.start();
			thread3.join();
			
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		//执行主线程中方法
		mainMethod();
	}
	
	public static void mainMethod() {
		for(int i=1;i<5;i++) {
			System.out.println("主线程>>"+Thread.currentThread().getName()+":数值>>"+i);
		}
	} 
	
}

结果:

主线程名称>>main
继承Thread线程名称>>Thread-0
继承Thread>>Thread-0:数值>>10
继承Thread>>Thread-0:数值>>11
继承Thread>>Thread-0:数值>>12
继承Thread>>Thread-0:数值>>13
继承Thread>>Thread-0:数值>>14
继承Thread>>Thread-0:数值>>15
继承Thread线程名称>>Thread-1
继承Thread>>Thread-1:数值>>20
继承Thread>>Thread-1:数值>>21
继承Thread>>Thread-1:数值>>22
继承Thread>>Thread-1:数值>>23
继承Thread>>Thread-1:数值>>24
继承Thread>>Thread-1:数值>>25
继承Thread线程名称>>Thread-2
继承Thread>>Thread-2:数值>>30
继承Thread>>Thread-2:数值>>31
继承Thread>>Thread-2:数值>>32
继承Thread>>Thread-2:数值>>33
继承Thread>>Thread-2:数值>>34
继承Thread>>Thread-2:数值>>35
主线程>>main:数值>>1
主线程>>main:数值>>2
主线程>>main:数值>>3
主线程>>main:数值>>4

第二种是在主线程的主方法里面使用join()方法,第一个子线程启动后,join一下,那么主线程就会被阻塞,直到该线程执行完毕才会向下执行其它代码。

第一个子线程里的目标方法执行完,第二个子线程在第一个子线程代码内join;第二个子线程目标方法执行完,第三个子线程在第二个子线程代码内join。等第三个子线程join完毕,第二个子线程、第一个子线程才算执行完毕,此时回到主线程。

public class Test {
	//主方法本身所在的是主线程
	public static void main(String[] args) {
		System.out.println("主线程名称>>"+Thread.currentThread().getName());
		//创建继承Thread类的多线程对象
		try {
			Thread thread1=new MyThread1();		
	
			//创建第一个子线程
			thread1.start();
			//在主线程中出现join方法,主线程被挂起,直至调用join方法的线程(thread对象)执行完毕才会向下执行
			thread1.join();
			
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		//执行主线程中方法
		mainMethod();
	}
	
	public static void mainMethod() {
		for(int i=1;i<5;i++) {
			System.out.println("主线程>>"+Thread.currentThread().getName()+":数值>>"+i);
		}
	} 
	
}

public class MyThread1 extends Thread{
	@Override
	public void run() {
		System.out.println("继承Thread线程名称>>"+Thread.currentThread().getName());
		//目标方法
		otherMethod();
		try {
			//创建第二个子线程
			Thread thread2=new MyThread2();
			thread2.start();
			thread2.join();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
			
	}
	public void otherMethod() {
		for(int i=10;i<=15;i++) {		
			System.out.println("继承Thread>>"+Thread.currentThread().getName()+":数值>>"+i);
		}
	}
}

public class MyThread2 extends Thread{
	@Override
	public void run() {
		System.out.println("继承Thread线程名称>>"+Thread.currentThread().getName());
		//目标方法
		otherMethod();
		try {
			//创建第三个子线程
			Thread thread3=new MyThread3();
			thread3.start();
			thread3.join();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
	public void otherMethod() {
		for(int i=20;i<=25;i++) {		
			System.out.println("继承Thread>>"+Thread.currentThread().getName()+":数值>>"+i);
		}
	}
}

public class MyThread3 extends Thread{
	@Override
	public void run() {
		System.out.println("继承Thread线程名称>>"+Thread.currentThread().getName());
		otherMethod();

	}
	public void otherMethod() {
		for(int i=30;i<=35;i++) {		
			System.out.println("继承Thread>>"+Thread.currentThread().getName()+":数值>>"+i);
		}
	}
}

结果:

主线程名称>>main
继承Thread线程名称>>Thread-0
继承Thread>>Thread-0:数值>>10
继承Thread>>Thread-0:数值>>11
继承Thread>>Thread-0:数值>>12
继承Thread>>Thread-0:数值>>13
继承Thread>>Thread-0:数值>>14
继承Thread>>Thread-0:数值>>15
继承Thread线程名称>>Thread-1
继承Thread>>Thread-1:数值>>20
继承Thread>>Thread-1:数值>>21
继承Thread>>Thread-1:数值>>22
继承Thread>>Thread-1:数值>>23
继承Thread>>Thread-1:数值>>24
继承Thread>>Thread-1:数值>>25
继承Thread线程名称>>Thread-2
继承Thread>>Thread-2:数值>>30
继承Thread>>Thread-2:数值>>31
继承Thread>>Thread-2:数值>>32
继承Thread>>Thread-2:数值>>33
继承Thread>>Thread-2:数值>>34
继承Thread>>Thread-2:数值>>35
主线程>>main:数值>>1
主线程>>main:数值>>2
主线程>>main:数值>>3
主线程>>main:数值>>4

目前来看两种方式结果相同,但是线程之间穿插执行,只能是第二种方式。比如第一个子线程待第二个子线程结束之后还要执行一段代码。

猜你喜欢

转载自blog.csdn.net/JWbonze/article/details/90033400