场景:
程序要通过多线程来处理相关业务,然后通过主线程判断子线程是否完成,然后再进行其它操作。
解决方案:利用java API (JDK1.5+)
CountDownLatch,一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。
主要使用的方法:
public CountDownLatch(int count);
public void countDown();
public void await() throws InterruptedException
从API源码找到的示例:
<pre>
* class Driver { // ...
* void main() throws InterruptedException {
* CountDownLatch startSignal = new CountDownLatch(1);
* CountDownLatch doneSignal = new CountDownLatch(N);
*
* for (int i = 0; i < N; ++i) // create and start threads
* new Thread(new Worker(startSignal, doneSignal)).start();
*
* doSomethingElse(); // don't let run yet
* startSignal.countDown(); // let all threads proceed
* doSomethingElse();
* doneSignal.await(); // wait for all to finish
* }
* }
*
* class Worker implements Runnable {
* private final CountDownLatch startSignal;
* private final CountDownLatch doneSignal;
* Worker(CountDownLatch startSignal, CountDownLatch doneSignal) {
* this.startSignal = startSignal;
* this.doneSignal = doneSignal;
* }
* public void run() {
* try {
* startSignal.await();
* doWork();
* doneSignal.countDown();
* } catch (InterruptedException ex) {} // return;
* }
*
* void doWork() { ... }
* }
*
* </pre>
*
* <p>Another typical usage would be to divide a problem into N parts,
* describe each part with a Runnable that executes that portion and
* counts down on the latch, and queue all the Runnables to an
* Executor. When all sub-parts are complete, the coordinating thread
* will be able to pass through await. (When threads must repeatedly
* count down in this way, instead use a {@link CyclicBarrier}.)
*
* <pre>
* class Driver2 { // ...
* void main() throws InterruptedException {
* CountDownLatch doneSignal = new CountDownLatch(N);
* Executor e = ...
*
* for (int i = 0; i < N; ++i) // create and start threads
* e.execute(new WorkerRunnable(doneSignal, i));
*
* doneSignal.await(); // wait for all to finish
* }
* }
*
* class WorkerRunnable implements Runnable {
* private final CountDownLatch doneSignal;
* private final int i;
* WorkerRunnable(CountDownLatch doneSignal, int i) {
* this.doneSignal = doneSignal;
* this.i = i;
* }
* public void run() {
* try {
* doWork(i);
* doneSignal.countDown();
* } catch (InterruptedException ex) {} // return;
* }
*
* void doWork() { ... }
* }
即:
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();
}
}
}
}
在我的开发中的场景:
手工统计功能,在后台因为使用了多线程,所以当用户一点击完统一,前台就打印出统计成功,实际后台程序还不运行,不断地计算,因此要使用上面的方法来解决,等待线程工作完成时前台才输出统计完成。符合业务逻辑。
分享到:
相关推荐
在主动式中,主线程会主动去检测某个标志位,判断子线程是否已经完成。这种方式需要主线程不断地检查子线程的状态,直到子线程完成。 被动式 在被动式中,主线程会被动地等待子线程的结束。这种方式更加符合人们的...
在主线程中,检查列表是否为空或线程是否都在运行,如果所有线程都完成了,就可以继续主线程的任务。 每种方法都有其适用场景,根据实际情况选择合适的方法。在处理大量并发任务时,合理地使用并发工具可以提高程序...
主线程可以通过检查列表是否为空来判断所有子线程是否已经完成。 下面是这种方法的实现细节: 1. 定义一个静态的`List<Thread>`变量`runningThreads`,用于存储正在运行的子线程。 2. 在`ImportThread`的构造函数...
在Java中实现打印素数的程序是一项基础但重要的任务,这有助于理解和掌握循环、条件判断以及数学逻辑在编程中的应用。下面将详细解释如何通过Java编写一个打印素数的程序。 首先,我们需要理解基本的算法。一个常见...
每个Java程序都有一个隐含的主线程,例如在应用程序中由main方法启动,在Applet中由浏览器启动。Java通过线程实现了系统的异步执行,使得程序能够同时处理多个任务。 创建Java线程主要有两种方式: 1. 继承Thread类...
- **检测线程状态**:`isAlive()`方法可以用来判断线程是否存活,但无法区分线程是否处于运行状态还是阻塞状态。 - **进入睡眠状态**:`sleep()`方法可以使线程进入睡眠状态。 #### 五、多线程的实现 在Java中,有...
本资源提供了一个简单方法来判断WPF应用的主线程界面是否出现卡顿情况。下面将详细介绍这个方法及其相关知识点。 一、主线程与UI线程 在WPF应用中,所有与用户交互的操作都是在主线程(也称为UI线程)上执行的。当...
在这个例子中,主线程会检查子线程的状态,判断它们是否已经完成执行。 总的来说,这个例子展示了Java多线程的基本操作,包括创建、启动、管理和通信。理解和掌握这些概念对于进行并发编程是至关重要的,可以帮助...
- **执行异步或后台处理**:多线程允许程序执行后台任务,如文件下载、数据库查询等,而不阻塞主线程。 #### 二、Java线程实现方式 ##### 2.1 继承Thread类 创建一个新的线程最简单的方法是定义一个继承自`Thread`...
Java虚拟机(JVM)启动时,会创建一个进程,如`java.exe`,在这个进程中至少包含一个线程,即主线程,它负责执行`main`方法中的代码。除此之外,JVM还会启动其他线程,例如垃圾回收机制的线程。 创建线程主要有两种...
这种方式可以用来判断线程是否已经完成了其任务,因为`result`初始为1,执行完后变为0。 `Threading.Thread`的其他关键方法包括: - `start()`: 这个方法启动线程,并且自动调用`run()`方法。`run()`方法通常是...
主线程是非守护线程,如果主线程结束,但还有其他非守护线程在运行,JVM不会立即关闭,直到所有非守护线程都结束。守护线程是一种辅助线程,如垃圾回收线程,当没有非守护线程运行时,JVM会自动停止。创建一个守护...
// 确保所有线程都完成 try { threadA.join(); threadB.join(); threadC.join(); } catch (InterruptedException e) { e.printStackTrace(); } } } ``` 这里的`synchronized`关键字和`wait()`、`notifyAll...
为了避免阻塞主线程导致应用无响应(ANR),计算密集型或耗时操作应该在工作线程(也称为子线程)中执行。在本例中,生成随机数和控制循环这样的任务就适合在子线程中进行。 接下来,我们可以使用`Thread`类或者`...
`printMsg()` 方法检查当前线程是否是创建线程的线程(creatorThread)还是新创建的线程(this),并根据判断结果输出相应的信息。 总的来说,Java 中的线程是通过类和对象来表示的,提供了灵活的方式来实现并发和...
游戏中的主程序、用户交互以及牌局逻辑通常运行在不同的线程上,以防止阻塞主线程导致的界面卡顿。例如,发牌过程可能在一个单独的线程中进行,确保即使在大量计算时,用户界面仍能保持响应。此外,多线程还能支持...
例如,在`main`方法中,主线程多次调用`tt.printMsg()`,这实际上是在不同线程之间进行了一种简单的通信。 #### 6. **代码调试与理解** 代码中出现了注释,比如“˼һ£ղŵĴе⣬鷳ٽһthis”,这些注释可能是原...
例如,在JoinTest.java的源码中,我们可以看到,通过new ThreadA("t1")新建了一个“线程t1”,然后启动了“线程t1”,并且调用了t1.join(),这样主线程main()就会等待“线程t1”的完成。 join方法的作用是让“主线...
ThreadGroup类提供了多种方法来管理线程组,例如getName()方法获取线程组的名字,isDaemon()方法判断线程组是否为后台线程组,list()方法列出线程组中的所有线程等。 四、实战示例 下面是一个简单的实战示例,演示...
Java程序启动时至少会有一个线程,即主线程,其他线程则可以由程序创建。 1.6 如何在Java程序中访问当前线程。可以使用Thread类的currentThread()方法获取当前正在运行的线程。 1.7 每个Java线程有哪些属性。线程...