首页

关于java主线程等待子线程常用几种实现方式代码demo示例

标签:线程同步,多线程,CountDownLatch,Semaphore,信号量,CompletableFuture     发布时间:2021-05-10   

一、前言

关于java场景多线程应用场景中,主任务线程任务结束完成依赖所有子任务线程都执行完成后,主任务才算完成最终任务,下面根据不同应用方式整理具体代码示例进行说明。

二、代码示例

1) 方法1:通过线程池executors.isTerminated()进行等待子任务线程完成

package thread.wait;@b@@b@import java.util.concurrent.ExecutorService;@b@import java.util.concurrent.Executors;@b@@b@public class MainThreadWaitTest1 {@b@	@b@	private static ExecutorService executors;@b@	@b@	public static void main(String[] args)  throws  Exception{@b@		//main job开始i@b@		System.out.println(Thread.currentThread().getName()+" run begin............");@b@		@b@		executors = Executors.newScheduledThreadPool(3);@b@		for(int i=0;i<10;i++){@b@			executors.submit(new Runnable() {@b@				@Override@b@				public@b@				void run() {@b@					//子线程开始工作@b@					System.out.println(Thread.currentThread().getName()+" working......");@b@					try {@b@						Thread.sleep(50);@b@					} catch (InterruptedException e) {@b@					}@b@					//子线程完成工作@b@					System.out.println(Thread.currentThread().getName()+" work finished......");@b@				}@b@			}); @b@		}@b@		@b@		executors.shutdown();@b@		//等待@b@		while (!executors.isTerminated()) {@b@			System.out.println(Thread.currentThread().getName()+"等待子线程完成任务,waiting...");@b@			Thread.currentThread().sleep(500);@b@		}@b@		@b@		//等待所有子任务线程工作完成后,总的main线程算完成任务@b@		System.out.println(Thread.currentThread().getName()+" all jobs finished ***************");@b@	}@b@@b@}

控制台打印结果如下

main run begin............@b@pool-1-thread-2 working......@b@main等待子线程完成任务,waiting...@b@pool-1-thread-1 working......@b@pool-1-thread-3 working......@b@pool-1-thread-3 work finished......@b@pool-1-thread-1 work finished......@b@pool-1-thread-2 work finished......@b@pool-1-thread-1 working......@b@pool-1-thread-2 working......@b@pool-1-thread-3 working......@b@pool-1-thread-3 work finished......@b@pool-1-thread-2 work finished......@b@pool-1-thread-1 work finished......@b@pool-1-thread-2 working......@b@pool-1-thread-3 working......@b@pool-1-thread-1 working......@b@pool-1-thread-2 work finished......@b@pool-1-thread-2 working......@b@pool-1-thread-1 work finished......@b@pool-1-thread-3 work finished......@b@pool-1-thread-2 work finished......@b@main all jobs finished ***************

2) 方法2:Semaphore信号量方式 - 通过 acquire() 获取一个许可,如果没有就等待,而 release() 释放一个许可。

package thread.wait;@b@@b@import java.util.concurrent.ExecutorService;@b@import java.util.concurrent.Executors;@b@import java.util.concurrent.Semaphore;@b@@b@public class MainThreadWaitTest2 {@b@	@b@	private  static  Semaphore semaphore=new Semaphore(3);@b@	@b@	private static ExecutorService executors;@b@	@b@	public static void main(String[] args)  throws  Exception{@b@		//main job开始i@b@		System.out.println(Thread.currentThread().getName()+" run begin............");@b@		@b@		executors = Executors.newScheduledThreadPool(3);@b@		for(int i=0;i<10;i++){@b@			executors.submit(new Runnable() {@b@				@Override@b@				public void run() {@b@					try {@b@						semaphore.acquire();@b@						//子线程开始工作@b@						System.out.println(Thread.currentThread().getName()+" working......");@b@						Thread.sleep(50);@b@					} catch (Exception e) {@b@						e.printStackTrace();@b@					}@b@					semaphore.release();@b@					//子线程完成工作@b@					System.out.println(Thread.currentThread().getName()+" work finished......");@b@				}@b@			}); @b@			Thread.sleep(50);@b@		}@b@		@b@		//等待所有子任务线程工作完成后,总的main线程算完成任务@b@		semaphore.acquireUninterruptibly();@b@//		semaphore.acquire(3);@b@		System.out.println(Thread.currentThread().getName()+" all jobs finished ***************");@b@	}@b@@b@}

控制台打印结果如下

main run begin............@b@pool-1-thread-1 working......@b@pool-1-thread-1 work finished......@b@pool-1-thread-1 working......@b@pool-1-thread-1 work finished......@b@pool-1-thread-1 working......@b@pool-1-thread-1 work finished......@b@pool-1-thread-2 working......@b@pool-1-thread-2 work finished......@b@pool-1-thread-3 working......@b@pool-1-thread-3 work finished......@b@pool-1-thread-1 working......@b@pool-1-thread-1 work finished......@b@pool-1-thread-2 working......@b@pool-1-thread-2 work finished......@b@pool-1-thread-3 working......@b@pool-1-thread-3 work finished......@b@pool-1-thread-1 working......@b@pool-1-thread-1 work finished......@b@pool-1-thread-2 working......@b@pool-1-thread-2 work finished......@b@main all jobs finished ***************

3) 方法3:CountDownLatch方式 - 是通过一个计数器来实现的,计数器的初始值是线程的数量。每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕。

package thread.wait;@b@@b@import java.util.concurrent.CountDownLatch;@b@import java.util.concurrent.ExecutorService;@b@import java.util.concurrent.Executors;@b@@b@public class MainThreadWaitTest3 {@b@	@b@	private static final CountDownLatch countDownLatch = new CountDownLatch(10);@b@	@b@	private static ExecutorService executors;@b@	@b@	public static void main(String[] args)  throws  Exception{@b@		//main job开始i@b@		System.out.println(Thread.currentThread().getName()+" run begin............");@b@		@b@		executors = Executors.newScheduledThreadPool(3);@b@		for(int i=0;i<10;i++){@b@			executors.submit(new Runnable() {@b@				@Override@b@				public@b@				void run() {@b@					try {@b@						//子线程开始工作@b@						System.out.println(Thread.currentThread().getName()+" working......");@b@//						Thread.sleep(50);@b@					} catch (Exception e) {@b@					} finally {@b@                        countDownLatch.countDown();  //这个不管是否异常都需要数量减,否则会被堵塞无法结束@b@                    }@b@@b@					//子线程完成工作@b@					System.out.println(Thread.currentThread().getName()+" work finished......");@b@				}@b@			}); @b@			Thread.sleep(50);@b@		}@b@		@b@		//等待所有子任务线程工作完成后,总的main线程算完成任务@b@		countDownLatch.await();@b@		System.out.println(Thread.currentThread().getName()+" all jobs finished ***************");@b@	}@b@@b@}

控制台打印结果如下

main run begin............@b@pool-1-thread-1 working......@b@pool-1-thread-1 work finished......@b@pool-1-thread-1 working......@b@pool-1-thread-1 work finished......@b@pool-1-thread-1 working......@b@pool-1-thread-1 work finished......@b@pool-1-thread-2 working......@b@pool-1-thread-2 work finished......@b@pool-1-thread-1 working......@b@pool-1-thread-1 work finished......@b@pool-1-thread-3 working......@b@pool-1-thread-3 work finished......@b@pool-1-thread-2 working......@b@pool-1-thread-2 work finished......@b@pool-1-thread-1 working......@b@pool-1-thread-1 work finished......@b@pool-1-thread-3 working......@b@pool-1-thread-3 work finished......@b@pool-1-thread-2 working......@b@pool-1-thread-2 work finished......@b@main all jobs finished ***************

4) 方法四 - CompletableFuture的allOf..join

package com.xwood.demo.threads;@b@@b@import java.util.concurrent.CompletableFuture;@b@import java.util.function.Consumer;@b@@b@public class CompletableFutureTest {@b@@b@@b@    public static void main(String[] args)  throws  Exception{@b@        //cf1子线程@b@        CompletableFuture cf1= CompletableFuture.runAsync(new Runnable() {@b@            @Override@b@            public void run() {@b@                System.out.println(Thread.currentThread().getName()+"@cf1 execute begin...");@b@                try {@b@                    Thread.sleep(1000);@b@                } catch (InterruptedException e) {}@b@                System.out.println(Thread.currentThread().getName()+"@cf1 execute finished...");@b@            }@b@        });@b@        //cf2子线程@b@        CompletableFuture cf2= CompletableFuture.runAsync(new Runnable() {@b@            @Override@b@            public void run() {@b@                System.out.println(Thread.currentThread().getName()+"@cf2 execute begin...");@b@                try {@b@                    Thread.sleep(1000);@b@                } catch (InterruptedException e) {}@b@                System.out.println(Thread.currentThread().getName()+"@cf2 execute finished...");@b@            }@b@        });@b@@b@        //等待所有cf1、cf2子线程执行后@b@        CompletableFuture.allOf(cf1,cf2).thenAccept(new Consumer<Void>() {@b@            @Override@b@            public void accept(Void aVoid) {@b@                System.out.println(Thread.currentThread().getName()+"@all execute begin...");@b@                try {@b@                    Thread.sleep(1000);@b@                } catch (InterruptedException e) {}@b@                System.out.println(Thread.currentThread().getName()+"@all execute finished...");@b@            }@b@        }).join();@b@        //简单等待处理@b@        //CompletableFuture.allOf(cf1,cf2).join();@b@@b@        //主main线程@b@        System.out.println(Thread.currentThread().getName()+"@main thread execute finished...");@b@@b@    }@b@@b@@b@}

控制台执行打印结果

ForkJoinPool.commonPool-worker-1@cf1 execute begin...@b@ForkJoinPool.commonPool-worker-2@cf2 execute begin...@b@ForkJoinPool.commonPool-worker-1@cf1 execute finished...@b@ForkJoinPool.commonPool-worker-2@cf2 execute finished...@b@ForkJoinPool.commonPool-worker-2@all execute begin...@b@ForkJoinPool.commonPool-worker-2@all execute finished...@b@main@main thread execute finished...

5)方法五 - future.get() 等待所有子任务执行完成,具体代码示例