码农之家 - 多线程
type: channel
link: http://blog.liyx.fun/index.php/tag/多线程/
items: C# CountdownEvent任务并行
items: Java多线程之以7种方式让主线程等待子线程结束

C# CountdownEvent任务并行
type: item
date: 2020-12-08T11:19:42+08:00
description: System.Threading.CountdownEvent 是一个同步基元，它在收到一定次数的信号之后，将会解除对其等待线程的锁定。 CountdownEvent 专门用于以下情况：您必须使用 ManualResetEvent 或 ManualResetEventSlim，并且必须在用信号通知事件之前手动递减一个变量。 例如，在分叉/联接方案中，您可以只创建一个信号计数为 5 的 CountdownEvent，然后在线程池上启动五个工作项，并且让每个工作项在完成时调用 Signal。 每次调用 Signal 时，信号计数都会递减 1。 在主线程上，对 Wait 的调用将会阻塞，直至信号计数为零。 CountdownEvent 具有这些附加功能： •可通过使用取消标记来取消等待操作。 •创建实例之后可以递增它的信号计数。 •通过调用 Reset 方法，可在 Wait 返回之后重用实例。 •实例公开 WaitHandle 以便与其他 .NET Framework 同步 API（例如 WaitAll）进行集成。private void CountEventTest() { CountdownEvent count = new CountdownEvent();//创建5个数量 Task[] task = new Task[]; count.Reset();//重置为4个数量 Action act = () => { MessageBox.Show("ok"); count.Signal();//通知已经有一个线程完成了 }; for (int i = ; i < task.Length; ++i) { task[i] = new Task(act); task[i].Start(); } count.Wait();//等待4个线程都完成 MessageBox.Show("end"); } 简单的说就是先设置多少个数量，然后Signal通知一个已经完成，Wait等待所有数量全部完成，则继续往下运行上述例子：先弹出4个OK，然后一个一个点掉，最后一个点掉的时候 弹出 end。CountdownEvent 和 Barrier 非常接近类似来源：https://www.bbsmax.com/A/gVdnM015Wl/

Java多线程之以7种方式让主线程等待子线程结束
type: item
date: 2020-12-08T11:02:01+08:00
description: 一、while循环对于“主线程如何获取子线程总运行时间”的问题，最开始想到的是使用while循环进行轮询：Thread t = new Thread(() -> { //子线程进行字符串连接操作 int num = 1000; String s = ""; for (int i = 0; i < num; i++) { s += "Java"; } System.out.println("t Over"); }); //开始计时 long start = System.currentTimeMillis(); System.out.println("start = " + start); t.start(); long end = 0; while(t.isAlive() == true){ end = System.currentTimeMillis(); try { Thread.sleep(10); }catch (InterruptedException e){ e.printStackTrace(); } } System.out.println("end = " + end); System.out.println("end - start = " + (end - start)); 二、Thread的join()方法使用join()方法，join()方法的作用，是等待这个线程结束；（t.join()方法阻塞调用此方法的线程(calling thread)，直到线程t完成，此线程再继续long start = System.currentTimeMillis(); System.out.println("start = " + start); t1.start(); try { t.join();//注意这里 } catch (InterruptedException e) { e.printStackTrace(); } long end = System.currentTimeMillis(); System.out.println("end = " + end); System.out.println("end - Start:" + (end - start)); 三、synchronized的等待唤醒机制Object lock = new Object(); Thread t = new Thread(() -> { int num = 1000; String s = ""; for (int i = 0; i < num; i++) { s += "Java"; } System.out.println("t Over"); synchronized (lock) {//获取对象锁 lock.notify();//子线程唤醒 } }); //计时 long start = System.currentTimeMillis(); System.out.println("start = " + start); //启动子线程 t.start(); try { synchronized (lock) {//这里也是一样 lock.wait();//主线程等待 } } catch (InterruptedException e) { e.printStackTrace(); } long end = System.currentTimeMillis(); System.out.println("end = " + end); System.out.println("end - start = " + (end - start)); 四、CountDownLatch使用java.util.concurrent包下的CountDownLatch类，简单来说，CountDownLatch类是一个计数器，可以设置初始线程数（设置后不能改变），在子线程结束时调用countDown()方法可以使线程数减一，最终为0的时候，调用CountDownLatch的成员方法wait()的线程就会取消BLOKED阻塞状态，进入RUNNABLE从而继续执行int threadNumber = 1; final CountDownLatch cdl = new CountDownLatch(threadNumber);//参数为线程个数 Thread t = new Thread(() -> { int num = 1000; String s = ""; for (int i = 0; i < num; i++) { s += "Java"; } System.out.println("t Over"); cdl.countDown(…