我正在编写一个具有5个线程的应用程序,这些线程可以同时从Web获取一些信息,并在缓冲区类中填充5个不同的字段。
当所有线程完成其工作时,我需要验证缓冲区数据并将其存储在数据库中。
我该怎么做(当所有线程完成工作时收到警报)?
我正在编写一个具有5个线程的应用程序,这些线程可以同时从Web获取一些信息,并在缓冲区类中填充5个不同的字段。
当所有线程完成其工作时,我需要验证缓冲区数据并将其存储在数据库中。
我该怎么做(当所有线程完成工作时收到警报)?
Answers:
我采用的方法是使用ExecutorService管理线程池。
ExecutorService es = Executors.newCachedThreadPool();
for(int i=0;i<5;i++)
es.execute(new Runnable() { /* your task */ });
es.shutdown();
boolean finished = es.awaitTermination(1, TimeUnit.MINUTES);
// all tasks have finished or the time has been reached.
while(!es.awaitTermination(1, TimeUnit.MINUTES));
es.shutdown();
吗?如果我编写了代码,并在其中使用es.execute(runnableObj_ZipMaking);
in try
块执行了一个线程,然后finally
调用了该怎么办boolean finshed = es.awaitTermination(10, TimeUnit.MINUTES);
?因此,我认为这应该等到所有线程完成工作或发生超时(无论哪个优先)后,我的假设是正确的吗?或致电shutdown()
是强制性的?
您可以join
到线程。连接阻塞直到线程完成。
for (Thread thread : threads) {
thread.join();
}
请注意,它join
会引发一个InterruptedException
。您必须决定如果发生这种情况该怎么办(例如,尝试取消其他线程以防止不必要的工作完成)。
t.join();
表示当前线程一直阻塞直到线程t
终止。它不影响线程t
。
看看各种解决方案。
join()
API已在Java的早期版本中引入。自JDK 1.5发行以来,此并发包提供了一些不错的选择。
执行给定的任务,并在完成所有操作后返回持有其状态和结果的期货列表。
请参考此相关的SE问题以获取代码示例:
一种同步帮助,它允许一个或多个线程等待,直到在其他线程中执行的一组操作完成为止。
一个CountDownLatch初始化为给定数。由于该
countDown()
方法的调用,直到当前计数达到零为止,await方法将阻塞,此后所有释放的线程将被释放,并且任何随后的await调用将立即返回。这是一种一次性现象-无法重置计数。如果需要用于重置计数的版本,请考虑使用CyclicBarrier。
请参阅此问题以了解 CountDownLatch
遍历提交给以下对象后创建的所有Future对象ExecutorService
除了Thread.join()
其他建议外,java 5引入了执行程序框架。在那里,您不使用Thread
对象。相反,您将Callable
或Runnable
对象提交给执行者。有一个特殊的执行程序,旨在执行多个任务并按顺序返回其结果。那是ExecutorCompletionService
:
ExecutorCompletionService executor;
for (..) {
executor.submit(Executors.callable(yourRunnable));
}
然后,您可以重复调用,take()
直到没有其他Future<?>
要返回的对象为止,这意味着所有对象都已完成。
根据您的情况,另一件事可能是相关的CyclicBarrier
。
一种同步辅助工具,它允许一组线程全部互相等待以到达一个公共的障碍点。CyclicBarriers在涉及固定大小的线程方的程序中很有用,该线程方有时必须互相等待。屏障被称为循环屏障,因为它可以在释放等待线程之后重新使用。
executor.submit
返回Future<?>
。我会将这些期货添加到列表中,然后遍历该列表并调用get
每个期货。
Executors
,例如Executors.newCachedThreadPool
(或类似的)
CountDownLatch
对象的另一种可能性是,它在简单情况下很有用:由于您事先知道线程数,因此请使用相关计数对其进行初始化,然后将该对象的引用传递给每个线程。
完成任务后,每个线程都会调用CountDownLatch.countDown()
,这会减少内部计数器的数量。在启动所有其他线程之后,主线程应执行CountDownLatch.await()
阻塞调用。一旦内部计数器达到0,它将被释放。
请注意,使用此对象,InterruptedException
也可能引发。
等待/阻塞线程主线程,直到其他一些线程完成其工作。
如前所述@Ravindra babu
,可以通过各种方式来实现,但要举例说明。
java.lang.Thread。join() 从:1.0
public static void joiningThreads() throws InterruptedException {
Thread t1 = new Thread( new LatchTask(1, null), "T1" );
Thread t2 = new Thread( new LatchTask(7, null), "T2" );
Thread t3 = new Thread( new LatchTask(5, null), "T3" );
Thread t4 = new Thread( new LatchTask(2, null), "T4" );
// Start all the threads
t1.start();
t2.start();
t3.start();
t4.start();
// Wait till all threads completes
t1.join();
t2.join();
t3.join();
t4.join();
}
从以下版本开始java.util.concurrent.CountDownLatch :1.5
.countDown()
«减少锁存器组的计数。.await()
«等待方法将阻塞,直到当前计数达到零为止。如果你创建了latchGroupCount = 4
那么countDown()
应该叫4倍,使数0,所以,这await()
将释放阻塞线程。
public static void latchThreads() throws InterruptedException {
int latchGroupCount = 4;
CountDownLatch latch = new CountDownLatch(latchGroupCount);
Thread t1 = new Thread( new LatchTask(1, latch), "T1" );
Thread t2 = new Thread( new LatchTask(7, latch), "T2" );
Thread t3 = new Thread( new LatchTask(5, latch), "T3" );
Thread t4 = new Thread( new LatchTask(2, latch), "T4" );
t1.start();
t2.start();
t3.start();
t4.start();
//latch.countDown();
latch.await(); // block until latchGroupCount is 0.
}
Threaded类的示例代码LatchTask
。要测试方法使用joiningThreads();
和latchThreads();
从主要方法。
class LatchTask extends Thread {
CountDownLatch latch;
int iterations = 10;
public LatchTask(int iterations, CountDownLatch latch) {
this.iterations = iterations;
this.latch = latch;
}
@Override
public void run() {
String threadName = Thread.currentThread().getName();
System.out.println(threadName + " : Started Task...");
for (int i = 0; i < iterations; i++) {
System.out.println(threadName + " : " + i);
MainThread_Wait_TillWorkerThreadsComplete.sleep(1);
}
System.out.println(threadName + " : Completed Task");
// countDown() « Decrements the count of the latch group.
if(latch != null)
latch.countDown();
}
}
CyclicBarrier barrier = new CyclicBarrier(3);
barrier.await();
例如,请参考此Concurrent_ParallelNotifyies类。执行器框架:我们可以使用ExecutorService创建线程池,并使用Future跟踪异步任务的进度。
submit(Runnable)
,submit(Callable)
它返回Future对象。通过使用future.get()
函数,我们可以阻塞主线程,直到工作线程完成其工作为止。
invokeAll(...)
-返回Future对象的列表,通过它们可以获取每个Callable的执行结果。
@也可以看看
尽管与OP的问题无关,但如果您对仅使用一个线程进行同步(更确切地说,是集合点)感兴趣,则可以使用一个 Exchanger
就我而言,我需要暂停父线程,直到子线程执行某些操作,例如完成其初始化。一个CountDownLatch也是行之有效的。
执行程序服务可用于管理多个线程,包括状态和完成。请参阅http://programmingexamples.wikidot.com/executorservice
试试这个,会起作用。
Thread[] threads = new Thread[10];
List<Thread> allThreads = new ArrayList<Thread>();
for(Thread thread : threads){
if(null != thread){
if(thread.isAlive()){
allThreads.add(thread);
}
}
}
while(!allThreads.isEmpty()){
Iterator<Thread> ite = allThreads.iterator();
while(ite.hasNext()){
Thread thread = ite.next();
if(!thread.isAlive()){
ite.remove();
}
}
}
现有答案说可能join()
每个线程。
但是有几种方法可以获取线程数组/列表:
ThreadGroup
管理线程。以下代码将使用该ThreadGruop
方法。它首先创建一个组,然后在创建每个线程时在构造函数中指定该组,然后可以通过以下方式获取线程数组ThreadGroup.enumerate()
SyncBlockLearn.java
import org.testng.Assert;
import org.testng.annotations.Test;
/**
* synchronized block - learn,
*
* @author eric
* @date Apr 20, 2015 1:37:11 PM
*/
public class SyncBlockLearn {
private static final int TD_COUNT = 5; // thread count
private static final int ROUND_PER_THREAD = 100; // round for each thread,
private static final long INC_DELAY = 10; // delay of each increase,
// sync block test,
@Test
public void syncBlockTest() throws InterruptedException {
Counter ct = new Counter();
ThreadGroup tg = new ThreadGroup("runner");
for (int i = 0; i < TD_COUNT; i++) {
new Thread(tg, ct, "t-" + i).start();
}
Thread[] tArr = new Thread[TD_COUNT];
tg.enumerate(tArr); // get threads,
// wait all runner to finish,
for (Thread t : tArr) {
t.join();
}
System.out.printf("\nfinal count: %d\n", ct.getCount());
Assert.assertEquals(ct.getCount(), TD_COUNT * ROUND_PER_THREAD);
}
static class Counter implements Runnable {
private final Object lkOn = new Object(); // the object to lock on,
private int count = 0;
@Override
public void run() {
System.out.printf("[%s] begin\n", Thread.currentThread().getName());
for (int i = 0; i < ROUND_PER_THREAD; i++) {
synchronized (lkOn) {
System.out.printf("[%s] [%d] inc to: %d\n", Thread.currentThread().getName(), i, ++count);
}
try {
Thread.sleep(INC_DELAY); // wait a while,
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.printf("[%s] end\n", Thread.currentThread().getName());
}
public int getCount() {
return count;
}
}
}
主线程将等待组中的所有线程完成。
在您的主线程中使用它:while(!executor.isTerminated()); 从执行程序服务启动所有线程后,放置此行代码。这只会在执行程序启动的所有线程完成后才启动主线程。确保调用executor.shutdown(); 在上述循环之前。