多线程同步-主线程等待所有子线程完成案例

有时候我们会遇到这样的问题:做一个大的事情可以被分解为做一系列相似的小的事情,而小的事情无非就是参数上有可能不相同而已!

此时,如果不使用线程,我们势必会浪费非常多的时间来完成整个大的事情,而使用线程的话将会存在这样的问题:

主线程启动所有子线程并发执行后主线程就直接返回了,导致外部函数判读整个大的事情完成了,但是实际上并没有完成!

针对以上情况我想我会采用多线程方式执行同时解决主线程等待子线程的问题。如图:

在这里我使用Java进行案例分析。

首先建立一个线程管理类,用于启动所有子线程和等待所有子线程完成,在这里不使用休眠一段时间后循环检测的方式(消耗CUP同时消耗时间,全部完成时间不够及时等缺点);而是使用等待临界值的方式。ThreadManager.java如下:

public class ThreadManager implements NotifyInterface {
	private final Object mLock = new Object();
	private int mCount = 0;
	private int endCount = 0;

	public ThreadManager(int count) {
		System.out.println("Manager In.");

		this.mCount = count;

		this.addThread();

		synchronized (mLock) {
			while (true) {
				if (checkEnd())
					break;
				try {
					mLock.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}

		System.out.println("Manager Out.");
	}

	private void addThread() {
		System.out.println("Manager addThread().");

		for (int i = 1; i <= mCount; i++) {
			ThreadDoThing dThread = new ThreadDoThing(i, "T" + i, this);
			// Start
			dThread.start();
		}

	}

	private boolean checkEnd() {
		boolean bFlag = false;
		bFlag = endCount >= mCount;

		System.out.println("Manager checkEnd().Return is:" + bFlag);

		return bFlag;
	}

	@Override
	public void runEnd() {
		synchronized (mLock) {
			++endCount;

			mLock.notifyAll();
		}
	}
}

此类集成自:NotifyInterface接口,NotifyInterface是用于子线程通知主线程自己已经完成工作所用类,ThreadManager实例化时将传入一个int值,用于设置启动的子线程数,当然这里是为了简单介绍所以采用的这样的方式,实际情况可能更加复杂。

在实例化后  进入构造方法,此时将会启动子线程,启动后进入循环等待中,当检测到所有子线程完成时就退出循环,没有就将进入临界值等待,直到通过接口通知主线程完成时将会通知临界值一次,此时循环将会执行一次,如果不满足退出条件将继续等待临界值。直到满足为止。

NotifyInterface接口如下:

public interface NotifyInterface {

	public abstract void runEnd();

}

测试用的子线程ThreadDoThing.java如下:

public class ThreadDoThing extends Thread {
	private NotifyInterface mInterface = null;
	private int mId = 0;
	private String mArgs = null;

	public ThreadDoThing(int id, String args, NotifyInterface iface) {
		this.mId = id;
		this.mArgs = args;
		this.AddInterface(iface);
	}

	public void AddInterface(NotifyInterface iface) {
		this.mInterface = iface;
	}

	@Override
	public void run() {
		System.out.println("ThreadDoThing Id is:" + this.mId + " Args is:" + this.mArgs);
		System.out.println(this.mId + ":Doing...");

		int sleepTime = (int) (Math.random() * 1000);

		try {
			Thread.sleep(sleepTime);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(this.mId + ":SleepTime is:" + sleepTime);

		this.notifyEnd();

		System.out.println(this.mId + ":Do End.");
	}

	private void notifyEnd() {
		if (this.mInterface != null)
			this.mInterface.runEnd();

		System.out.println(this.mId + ":Notify End.");
	}
}

此类继承自Thread类,可直接重写Run()方法完成所做工作!

在工作中,我使用了随机一个1s内的休眠来代替所做工作的时间,完成后调用接口通知完成。

测试方法如下:

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ThreadManager manager = new ThreadManager(10);
	}

测试结果:

Manager In.
Manager addThread().
ThreadDoThing Id is:1 Args is:T1
ThreadDoThing Id is:2 Args is:T2
2:Doing...
1:Doing...
ThreadDoThing Id is:3 Args is:T3
ThreadDoThing Id is:4 Args is:T4
3:Doing...
4:Doing...
ThreadDoThing Id is:5 Args is:T5
5:Doing...
ThreadDoThing Id is:6 Args is:T6
Manager checkEnd().Return is:false
ThreadDoThing Id is:8 Args is:T8
ThreadDoThing Id is:7 Args is:T7
8:Doing...
ThreadDoThing Id is:9 Args is:T9
9:Doing...
6:Doing...
ThreadDoThing Id is:10 Args is:T10
7:Doing...
10:Doing...
3:SleepTime is:111
3:Notify End.
3:Do End.
Manager checkEnd().Return is:false
5:SleepTime is:142
5:Notify End.
Manager checkEnd().Return is:false
5:Do End.
4:SleepTime is:199
4:Notify End.
Manager checkEnd().Return is:false
4:Do End.
7:SleepTime is:342
7:Notify End.
Manager checkEnd().Return is:false
7:Do End.
10:SleepTime is:346
10:Notify End.
Manager checkEnd().Return is:false
10:Do End.
6:SleepTime is:397
6:Notify End.
Manager checkEnd().Return is:false
6:Do End.
9:SleepTime is:468
9:Notify End.
Manager checkEnd().Return is:false
9:Do End.
1:SleepTime is:475
1:Notify End.
Manager checkEnd().Return is:false
1:Do End.
2:SleepTime is:686
Manager checkEnd().Return is:false
2:Notify End.
2:Do End.
8:SleepTime is:828
8:Notify End.
Manager checkEnd().Return is:true
8:Do End.
Manager Out.

实际情况可能更加复杂,甚至子线程下还有更多的子线程!

具体情况大家可以衍生考虑,检测是否全部返回也可以有多种方式甚至设置添加一个定时器之类的。

以后有时间画一个详细点的图!

多线程同步-主线程等待所有子线程完成案例

时间: 2024-10-20 10:16:52

多线程同步-主线程等待所有子线程完成案例的相关文章

[Java][Android] 多线程同步-主线程等待全部子线程完毕案例

有时候我们会遇到这种问题:做一个大的事情能够被分解为做一系列相似的小的事情,而小的事情无非就是參数上有可能不同样而已! 此时,假设不使用线程,我们势必会浪费许多的时间来完毕整个大的事情.而使用线程的话将会存在这种问题: 主线程启动全部子线程并发运行后主线程就直接返回了,导致外部函数判读整个大的事情完毕了,可是实际上并没有完毕! 针对以上情况我想我会採用多线程方式运行同一时候解决主线程等待子线程的问题.如图: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQ

Java多线程--让主线程等待所有子线程执行完毕

数据量很大百万条记录,因此考虑到要用多线程并发执行,在写的过程中又遇到问题,我想统计所有子进程执行完毕总共的耗时,在第一个子进程创建前记录当前时间用System.currentTimeMillis()在最后一个子进程结束后记录当前时间,两次一减得到的时间差即为总共的用时,代码如下 Java代码   long tStart = System.currentTimeMillis(); System.out.println(Thread.currentThread().getName() + "开始&

Java多线程、主线程等待所有子线程执行完毕、共享资源

1.Java创建与启动线程 Java提供两种方式创建和启动线程:1.直接Thread类,2.实现Runable接口. 1.1  继承Thread类 public class myThread extends Thread { public void run(){ for(int i=0;i<5;i++){ System.out.println(this.getName()+":"+i); } } public static void main(String[] args){ //

Java多线程--让主线程等待所有子线程执行完毕 join

首先从公司一道笔试题开始 1 package test; 2 3 public class Test implements Runnable { 4 5 public int i = 0; 6 7 @Override 8 public void run() { 9 try { 10 Thread.sleep(1000); 11 } catch (InterruptedException e) { 12 // TODO Auto-generated catch block 13 e.printSt

java主线程等待所有子线程执行完毕在执行(常见面试题)

java主线程等待所有子线程执行完毕在执行(常见面试题) java主线程等待所有子线程执行完毕在执行,这个需求其实我们在工作中经常会用到,比如用户下单一个产品,后台会做一系列的处理,为了提高效率,每个处理都可以用一个线程来执行,所有处理完成了之后才会返回给用户下单成功,下面就说一下我能想到的方法,欢迎大家批评指正: 用sleep方法,让主线程睡眠一段时间,当然这个睡眠时间是主观的时间,是我们自己定的,这个方法不推荐,但是在这里还是写一下,毕竟是解决方法 2.使用Thread的join()等待所有

Java主线程等待所有子线程执行完毕再执行解决办法集

Java主线程等待所有子线程执行完毕在执行,其实在我们的工作中经常的用到,比如说主线程要返回一个响应用户的值,但这个值得赋值过程是由过个子线程来完成的(模拟一个实际开发的情景),所以主线程必须等待子线程执行完毕,再响应用户:否则,响应用户的是一个无意义的值. 那么如何确保所有的子线程执行完毕了.一般的有如下方法: 1  让主线程等待,或着睡眠几分钟.用Thread.sleep()或者TimeUnit.SECONDS.sleep(5); 如下: package andy.thread.tradit

主线程等待所有子线程执行完成之后再继续往下执行的解决方案

问题背景: 目前需要解析十多个Excel文件并将数据导入到数据库,文件导出完成之后还有后续步骤需要处理,例如更新批次状态. 如果采用单线程的方式顺序去处理每个文件的话,感觉有点慢,虽说不算是特别慢,但是由于用户需要等待导入结果, 考虑到用于体验问题,因此需要坐下性能优化.既然是性能优化,基本都是考虑到使用多线程并发处理.但是多线线程有个问题, 就是启动多个线程后,如何让当前线程等待这些子线程执行完毕,因为需要根据所以子线程的执行结果来更新批次状态 解决方案1: 基本思路是这样: 每个SubThr

Java多线程--让主线程等待子线程执行完毕

使用Java多线程编程时经常遇到主线程需要等待子线程执行完成以后才能继续执行,那么接下来介绍一种简单的方式使主线程等待. java.util.concurrent.CountDownLatch 使用countDownLatch.await()方法非常简单的完成主线程的等待: public class ThreadWait { public static void main(String[] args) throws InterruptedException { int threadNumber

Java并发编程原理与实战六:主线程等待子线程解决方案

本文将研究的是主线程等待所有子线程执行完成之后再继续往下执行的解决方案 public class TestThread extends Thread { public void run() { System.out.println(this.getName() + "子线程开始"); try { // 子线程休眠五秒 Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.