java 开启一个线程前判断_多线程---java判断多线程结束

需求应用场景

我们多线程抓取数据或者多线程执行任务时,有时候需要多线程执行完后      才能执行其他的任务。

这种情况下  我们就需要判断多线程什么时候执行完。有以下几种方法(推荐方法二)

方法一 isTerminated

使用isTerminated来判断所有任务都已完成,会返回true。但是前提是启用shutdown顺序关闭。

shutdown

void shutdown()

启动一次顺序关闭,执行以前提交的任务,但不接受新任务。如果已经关闭,则调用没有其他作用。

抛出:

SecurityException - 如果安全管理器存在并且关闭,此 ExecutorService 可能操作某些不允许调用者修改的线程(因为它没有保持RuntimePermission("modifyThread")),或者安全管理器的 checkAccess 方法拒绝访问。

isTerminated

boolean isTerminated()

如果关闭后所有任务都已完成,则返回 true。注意,除非首先调用 shutdown 或 shutdownNow,否则 isTerminated 永不为 true。

返回:

如果关闭后所有任务都已完成,则返回 true

使用例子

先调用shundown再调用isTerminated判断

/**

* 采用线程池开启多个子线程,主线程等待所有的子线程执行完毕

*/

public static void moreThread() {

try {

int threadNum = 0;

for (int i = 0; i < 10; i++) {

threadNum++;

final int currentThreadNum = threadNum;

exe.execute(new Runnable() {

@Override

public void run() {

try {

System.out.println("子线程[" + currentThreadNum + "]开启");

Thread.sleep(1000*10);

} catch (InterruptedException e) {

e.printStackTrace();

}finally{

System.out.println("子线程[" + currentThreadNum + "]结束");

}

}

});

}

System.out.println("已经开启所有的子线程");

exe.shutdown();

System.out.println("shutdown():启动一次顺序关闭,执行以前提交的任务,但不接受新任务。");

while(true){

if(exe.isTerminated()){

System.out.println("所有的子线程都结束了!");

break;

}

Thread.sleep(1000);

}

} catch (InterruptedException e) {

e.printStackTrace();

}finally{

System.out.println("主线程结束");

}

}

输出结果

子线程[1]开启

子线程[6]开启

子线程[2]开启

子线程[5]开启

子线程[9]开启

已经开启所有的子线程

子线程[3]开启

子线程[7]开启

子线程[10]开启

shutdown():启动一次顺序关闭,执行以前提交的任务,但不接受新任务。

子线程[4]开启

子线程[8]开启

子线程[6]结束

子线程[3]结束

子线程[7]结束

子线程[2]结束

子线程[1]结束

子线程[5]结束

子线程[9]结束

子线程[4]结束

子线程[10]结束

子线程[8]结束

所有的子线程都结束了!

主线程结束

方法二CountDownLatch

CountDownLatch是一个同步辅助类,用来判断多线程是否执行完成。

它的原理是首先声明一共运行多少个线程任务,然后每完成一个线程任务,计数器就减一,当计数器等于0,说明所有的多线程都运行完成了。

主要方法

public CountDownLatch(int count);

public void countDown();

public void await() throws InterruptedException

构造方法参数指定了计数的次数

countDown方法,当前线程调用此方法,则计数减一

await方法,调用此方法会一直阻塞当前线程,直到计时器的值为0。

使用方法

如果你确定了你开启的线程数。

那么在主程序运行前。

CountDownLatch countdown = new CountDownLatch(10);//这里的10就是你的子线程数。

在每个子线程结束后,调用 countdown.countDown();

在主线程里启动子线程的方法后面添加。

countdown.await();//这里进行同步等待

等所有子线程结束后,执行 countdown.await()后面的代码。

使用例子

public class CountDownLatchDemo {

final static SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

public static void main(String[] args) throws InterruptedException {

CountDownLatch latch=new CountDownLatch(2);//两个工人的协作

Worker worker1=new Worker("zhang san", 5000, latch);

Worker worker2=new Worker("li si", 8000, latch);

worker1.start();//

worker2.start();//

latch.await();//等待所有工人完成工作

System.out.println("all work done at "+sdf.format(new Date()));

}

static class Worker extends Thread{

String workerName;

int workTime;

CountDownLatch latch;

public Worker(String workerName ,int workTime ,CountDownLatch latch){

this.workerName=workerName;

this.workTime=workTime;

this.latch=latch;

}

public void run(){

System.out.println("Worker "+workerName+" do work begin at "+sdf.format(new Date()));

doWork();//工作了

System.out.println("Worker "+workerName+" do work complete at "+sdf.format(new Date()));

latch.countDown();//工人完成工作,计数器减一

}

private void doWork(){

try {

Thread.sleep(workTime);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

输出结果

Worker zhang san do work begin at 2011-04-14 11:05:11

Worker li si do work begin at 2011-04-14 11:05:11

Worker zhang san do work complete at 2011-04-14 11:05:16

Worker li si do work complete at 2011-04-14 11:05:19

all work done at 2011-04-14 11:05:19

方法三CyclicBarrier

CyclicBarrier ,一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。CyclicBarrier 支持一个可选的 Runnable 命令,在一组线程中的最后一个线程到达之后(但在释放所有线程之前),该命令只在每个屏障点运行一次。若在继续所有参与线程之前更新共享状态,此屏障操作 很有用。

主要方法

//设置parties、count及barrierCommand属性。

CyclicBarrier(int):

//当await的数量到达了设定的数量后,首先执行该Runnable对象。

CyclicBarrier(int,Runnable):

//通知barrier已完成线程

await():

使用例子

我们需要统计全国的业务数据。其中各省的数据库是独立的,也就是说按省分库。并且统计的数据量很大,统计过程也比较慢。为了提高性能,快速计算。我们采取并发的方式,多个线程同时计算各省数据,最后再汇总统计。在这里CyclicBarrier就非常有用。看代码:

主要类:

/**

* 各省数据独立,分库存偖。为了提高计算性能,统计时采用每个省开一个线程先计算单省结果,最后汇总。

*

* @author guangbo email:weigbo@163.com

*

*/

public class Total {

// private ConcurrentHashMap result = new ConcurrentHashMap();

public static void main(String[] args) {

TotalService totalService = new TotalServiceImpl();

CyclicBarrier barrier = new CyclicBarrier(5,

new TotalTask(totalService));

// 实际系统是查出所有省编码code的列表,然后循环,每个code生成一个线程。

new BillTask(new BillServiceImpl(), barrier, "北京").start();

new BillTask(new BillServiceImpl(), barrier, "上海").start();

new BillTask(new BillServiceImpl(), barrier, "广西").start();

new BillTask(new BillServiceImpl(), barrier, "四川").start();

new BillTask(new BillServiceImpl(), barrier, "黑龙江").start();

}

}

/**

* 主任务:汇总任务

*/

class TotalTask implements Runnable {

private TotalService totalService;

TotalTask(TotalService totalService) {

this.totalService = totalService;

}

public void run() {

// 读取内存中各省的数据汇总,过程略。

totalService.count();

System.out.println("=======================================");

System.out.println("开始全国汇总");

}

}

/**

* 子任务:计费任务

*/

class BillTask extends Thread {

// 计费服务

private BillService billService;

private CyclicBarrier barrier;

// 代码,按省代码分类,各省数据库独立。

private String code;

BillTask(BillService billService, CyclicBarrier barrier, String code) {

this.billService = billService;

this.barrier = barrier;

this.code = code;

}

public void run() {

System.out.println("开始计算--" + code + "省--数据!");

billService.bill(code);

// 把bill方法结果存入内存,如ConcurrentHashMap,vector等,代码略

System.out.println(code + "省已经计算完成,并通知汇总Service!");

try {

// 通知barrier已经完成

barrier.await();

} catch (InterruptedException e) {

e.printStackTrace();

} catch (BrokenBarrierException e) {

e.printStackTrace();

}

}

}

输出结果

开始计算--北京省--数据!

开始计算--上海省--数据!

北京省已经计算完成,并通知汇总Service!

开始计算--四川省--数据!

四川省已经计算完成,并通知汇总Service!

上海省已经计算完成,并通知汇总Service!

开始计算--广西省--数据!

广西省已经计算完成,并通知汇总Service!

开始计算--黑龙江省--数据!

黑龙江省已经计算完成,并通知汇总Service!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值