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

此时,假设不使用线程,我们势必会浪费许多的时间来完毕整个大的事情。而使用线程的话将会存在这种问题:

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

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

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcWl1anVlcg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

在这里我使用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.

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

详细情况大家能够衍生考虑,检測是否所有返回也能够有多种方式甚至设置加入一个定时器之类的。

以后有时间画一个具体点的图!

[Java][Android] 多线程同步-主线程等待全部子线程完毕案例的更多相关文章

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

    数据量很大百万条记录,因此考虑到要用多线程并发执行,在写的过程中又遇到问题,我想统计所有子进程执行完毕总共的耗时,在第一个子进程创建前记录当前时间用System.currentTimeMillis() ...

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

    java主线程等待所有子线程执行完毕在执行(常见面试题) java主线程等待所有子线程执行完毕在执行,这个需求其实我们在工作中经常会用到,比如用户下单一个产品,后台会做一系列的处理,为了提高效率,每个 ...

  3. java主线程结束和子线程结束之间的关系

    (一)Main线程是个非守护线程,不能设置成守护线程. 这是因为,main线程是由java虚拟机在启动的时候创建的.main方法开始执行的时候,主线程已经创建好并在运行了.对于运行中的线程,调用Thr ...

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

    使用Java多线程编程时经常遇到主线程需要等待子线程执行完成以后才能继续执行,那么接下来介绍一种简单的方式使主线程等待. java.util.concurrent.CountDownLatch 使用c ...

  5. java多线程实现主线程等待子线程执行完问题

    本文介绍两种主线程等待子线程的实现方式,以5个子线程来说明: 1.使用Thread的join()方法,join()方法会阻塞主线程继续向下执行. 2.使用Java.util.concurrent中的C ...

  6. Java主线程等待所有子线程执行完毕再执行解决办法(转)

    方法一: Thread.join()方法,亲测可行,thread.join()方法 Vector<Thread> ts = new Vector<Thread>(); for  ...

  7. Java中主线程如何捕获子线程抛出的异常

    首先明确线程代码的边界.其实很简单,Runnable接口的run方法所界定的边界就可以看作是线程代码的边界.Runnable接口中run方法原型如下: public void run(); 而所有的具 ...

  8. iOS开发之GCD同步主线程、异步主线程

    /** 在主线程执行block */ + (void)gs_synExecuteOnMainThread:(void (^)(void))block { if ((nil == block) || ( ...

  9. c/c++中主线程退出,子线程也会退出

    #include <windows.h> #include <process.h> /* _beginthread, _endthread */ #include <io ...

随机推荐

  1. CAD参数绘制直线(com接口)

    用户可以在CAD控件视区任意位置绘制直线. 主要用到函数说明: _DMxDrawX::DrawLine 绘制一个直线.详细说明如下: 参数 说明 DOUBLE dX1 直线的开始点x坐标 DOUBLE ...

  2. Sql Server cross apply和outer apply

    with result as( select t.str from( ' str union all ' str union all ' str union all ' str union all ' ...

  3. Google Chrome浏览器调试

    作为Web开发人员,我为什么喜欢Google Chrome浏览器 [原文地址:http://www.cnblogs.com/QLeelulu/archive/2011/08/28/2156402.ht ...

  4. redis的安装总结

    1. 下载redis安装包:> 可以用命令: wget http://download.redis.io/releases/redis-5.0.5.tar.gz, 或者直接从官网下载.2. 解压 ...

  5. 无法完成安装:'Cannot access storage file '/

    今天自己编译了spice-protocol spice-gtk spice qemu,然后想用virsh去创建一个虚机: # virsh define demo.xml     定义域 demo(从 ...

  6. winfrom 多线程 并发 和定时任务

    static void Main(string[] args) { //多个线程修改同一个值,使用lock锁解决并发 for (int i = 0; i < 4; i++) { Task.Fac ...

  7. PHP条件运算符的“坑”

    今天遇到一个关于PHP 嵌套使用条件运算符(ternary expressions)的问题 现象 先来看一段C语言代码(test.c): #include<stdio.h> int mai ...

  8. Buffer.from(str[, encoding])

    Buffer.from(str[, encoding]) Node.js FS模块方法速查 str {String} 需要编码的字符串 encoding {String} 编码时用到,默认:'utf8 ...

  9. Python之条件判断

    Python之条件判断 计算机之所以能做很多自动化的任务,因为它可以自己做条件判断. 比如,输入用户年龄,根据年龄打印不同的内容,在Python程序中,用if语句实现: age = 20 if age ...

  10. CC3200 TI 笔记

    I2C I2C总线是由Philips公司开发的一种简单.双向二线制同步串行总线.它只需要两根线即可在连接于总线上的器件之间传送信息. I2S I2S(Inter-IC Sound)总线, 又称 集成电 ...