java中的countdownlatch.
根据Java文档, CountDownLatch
是同步辅助辅助辅助装置允许一个或者多个线程等待直到在其他线程中执行的一组操作完成。
所以换句话说,CountDownLatch等待其他线程完成一组操作。
countdownlatch是用计数初始化的。
任何线程通常是主线程都会调用latch.awaits()方法,因此它将等待任一计数变为零,或者它被另一个线程中断,所有其他线程都需要呼叫 latch.countDown()
一旦他们完成了一些操作。
因此,只要减少1 latch.countDown()
方法被调用,所以如果计数是n表示可以使用的数量,因为n个线程必须完成一些动作或者某些操作必须完成n次。
CountDownLatch的缺点之一是,一旦计数为零,我们无法重用它。
为此,我们需要使用CyclicBarrier。
例如:
下图将使我们清除。
这是一个示例如何使用CountDownLatch。
假设,我们正在开发一个应用程序,因此它的主线程必须等待其他服务(线程),例如UI初始化,数据库初始化和日志记录服务完成。
所以CountDownLatch将用3个和主线程初始化,呼叫等待()方法,每个服务都会调用Latch.CountDown()一旦它们即将完成。
程序 :
创建一个名为UIInitialization.java的类。
完成后,此线程将执行leatal.countdown()。
package org.arpit.theitroad.thread; import java.util.concurrent.CountDownLatch; public class UIInitialization implements Runnable{ CountDownLatch latch; UIInitialization(CountDownLatch latch) { this.latch=latch; } @Override public void run() { System.out.println("Initializing UI"); try { Thread.sleep(3000); } catch (InterruptedException e) { //TODO Auto-generated catch block e.printStackTrace(); } System.out.println("Done with UI Initialization"); latch.countDown(); } }
创建名为loggingInitialization.java的类。
完成后,此线程将执行leatal.countdown()。
package org.arpit.theitroad.thread; import java.util.concurrent.CountDownLatch; public class LoggingInitialization implements Runnable{ CountDownLatch latch; LoggingInitialization(CountDownLatch latch) { this.latch=latch; } @Override public void run() { System.out.println("Initializing Logging"); try { Thread.sleep(2000); } catch (InterruptedException e) { //TODO Auto-generated catch block e.printStackTrace(); } System.out.println("Done with Logging Initialization"); latch.countDown(); } }
创建一个名为datdersinitialization.java的类。
完成后,此线程将执行leatal.countdown()。
package org.arpit.theitroad.thread; import java.util.concurrent.CountDownLatch; public class DatabaseInitialization implements Runnable{ CountDownLatch latch; DatabaseInitialization(CountDownLatch latch) { this.latch=latch; } @Override public void run() { System.out.println("Initializing Database"); try { Thread.sleep(5000); } catch (InterruptedException e) { //TODO Auto-generated catch block e.printStackTrace(); } System.out.println("Done with database Initialization"); latch.countDown(); } }
创建类CountDownLatchMain.java。
这将是主要线程,它将等待UIInitialization,DatabaseInitialization和LoggingInitialization。
package org.arpit.theitroad.thread; import java.util.concurrent.CountDownLatch; public class CountDownLatchMain { public static void main(String[] args) { try { CountDownLatch latch = new CountDownLatch(3); //Initializing three dependent thread for example:UI, database and logging UIInitialization uiInitialization = new UIInitialization(latch); Thread uiThread = new Thread(uiInitialization); DatabaseInitialization dataBaseInitialization = new DatabaseInitialization(latch); Thread databaseThread = new Thread(dataBaseInitialization); LoggingInitialization loggingInitialization = new LoggingInitialization(latch); Thread loggingThread = new Thread(loggingInitialization); uiThread.start(); databaseThread.start(); loggingThread.start(); //Main thread will wait until above threads get completed latch.await(); System.out.println("Initialization has been completed, main thread can proceed now"); } catch (InterruptedException e) { e.printStackTrace(); } } }
运行上面的程序时,我们将获取以下输出:
Initializing UI Initializing Database Initializing Logging Done with Logging Initialization Done with UI Initialization Done with database Initialization Initialization has been completed, main thread can proceed now
为什么不使用Join而不是CountDownLatch:
如我们所知,我们也可以使用此情况,但我们必须手动处理它。
现在大多数人使用ExecutorService用于处理线程,CountDownLatch适用于它。
由于CountDownLatch是面向的任务,我们可以向线程池提交多个任务,并且CountDownLatch将确保在一组其他依赖线程完成后确保执行原始线程。