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

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

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

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

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. webgl 的空间变换(下):空间变换

    在网上看了很多关于在三维世界中怎么把一个顶点经过一步步变化,最终呈现在我们的屏幕上的. 其实很多博客或者书籍已经讲的很清楚了,那为什么我还要特别再写一次博客来阐述自己观点呢?(这里只针对那些学习web ...

  2. HTML head meta标签详细

    <!DOCTYPE html> <!-- 使用 HTML5 doctype,不区分大小写 --> <html lang="zh-cmn-Hans"&g ...

  3. Google Chrome浏览器调试

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

  4. JavaScript exec()方法

    exec() 方法用于检索字符串中的正则表达式的匹配.返回一个数组,其中存放匹配的结果.如果未找到匹配,则返回值为 null. var str = "我今年25岁明年26岁后年27岁千年24 ...

  5. 运用 node + express + http-proxy-middleware 实现前端代理跨域的 详细实例哦

    一.你需要准备的知识储备 运用node的包管理工具npm 安装插件.中间件的基本知识: 2.express框架的一些基础知识,知道如何建立一个小的服务器:晓得如何快速的搭建一个express框架小应用 ...

  6. 如何自己实现session功能

    session字如其意,它的存在就是为了保持会话状态.PHP中的$_SESSION让我们很方便的使用它,但是如果PHP本身不提供这个功能,我们该如何实现呢?且听我慢慢忽悠. session的实现原理 ...

  7. Python之机器学习-波斯顿房价预测

    目录 波士顿房价预测 导入模块 获取数据 打印数据 特征选择 散点图矩阵 关联矩阵 训练模型 可视化 波士顿房价预测 导入模块 import pandas as pd import numpy as ...

  8. 前端性能分析-HTTPWatch和dynaTrace

  9. jsp学习之如何在web层创建Servlet

    jsp动态网页的文件目录结构如下: 1.src下存放java代码 2.包web_xx为web层 3.webcontent里面是jsp文件 jsp页面中的请求交付给servlet处理,在实际中 jsp的 ...

  10. java程序验证用户名密码和验证码登录的小例子

    package Study02; import java.util.Random; import java.util.Scanner; public class test { static Strin ...