I am starting multiple threads and the idea is to wait for only one of them(does not matter which one) to continue the main thread and ignoring the other threads. In other words the main thread starts several threads and then waits until the fastest thread joins. Any ideas how to implement such a thing?
There's several possibilities.
1. Use a CountDownLatch
The idea is to have a CountDownLatch set to 1. All tasks running on the relevant threads will end by calling countDown() on it.
The main thread will simply call await() on it, and as soon as the first task is finished, the latch will hit 0, and release the waiting main thread.
This approach works with raw Threads, as well as with an ExecutorService.
public class UseCountDownLatch {
public static void main(String[] args) {
int numberOfThreads = 5;
CountDownLatch countDownLatch = new CountDownLatch(1);
ExecutorService executorService = Executors.newFixedThreadPool(numberOfThreads);
for (int i = 0; i < numberOfThreads; i++) {
int print = i;
executorService.submit(() -> {
try {
TimeUnit.SECONDS.sleep(print * 3);
System.out.println(print);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
countDownLatch.countDown();
}
});
}
executorService.shutdown();
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Continue");
try {
executorService.awaitTermination(1, TimeUnit.MINUTES);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Done");
}
}
2. Use a CompletionService
Wrap your ExecutionService in a CompletionService, then just wait for the first result to come in, and ignore further results.
public class UseCompletionService {
public static void main(String[] args) {
int numberOfThreads = 5;
ExecutorService executorService = Executors.newFixedThreadPool(numberOfThreads);
CompletionService<Void> completionService = new ExecutorCompletionService<Void>(executorService);
for (int i = 0; i < numberOfThreads; i++) {
int print = i;
completionService.submit(() -> {
try {
TimeUnit.SECONDS.sleep(print * 3);
System.out.println(print);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return null;
});
}
executorService.shutdown();
try {
completionService.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Continue");
try {
executorService.awaitTermination(1, TimeUnit.MINUTES);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Done");
}
}
3. Use CompletableFutures
The CompletableFutures API is made to make tasks composable. The trick is simply to combine the CompletableFutures for each individual task in a CompletableFuture that completes as soon as any of its components completes. Then it's just a matter of getting the result from the composed CompletableFuture.
public class UseCompletableFuture {
public static void main(String[] args) {
int numberOfThreads = 5;
CompletableFuture<?>[] tasks = new CompletableFuture<?>[numberOfThreads];
for (int i = 0; i < numberOfThreads; i++) {
int print = i;
tasks[i] = CompletableFuture.runAsync(() -> {
try {
TimeUnit.SECONDS.sleep(print*3);
System.out.println(print);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
}
try {
CompletableFuture.anyOf(tasks).get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
System.out.println("Continue");
try {
CompletableFuture.allOf(tasks).get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
System.out.println("Done");
}
}
Related
I have the following mutlithreaded code. I want the LatchCode.doStuff() to wait until UncaughtExceptionHandler handler completes it work, but it wasn't. How could I make the main thread to wait for it. I need to propagate the exception to parent for some project requirement to log the error into DB (should happen at the end of processing). Following is the piece of code.
public class LatchExceptionTest {
public static void main(String[] args) {
LatchCode l = new LatchCode();
Cont c = new Cont();
try {
l.doStuff(c);
System.out.println("Main Thread - work completed");
if(!c.err.isEmpty())
throw new Exception(c.err.toString());
} catch (Exception e) {
System.out.println("trace printing start");
System.out.println(c.err.toString()); // log errors to DB
System.out.println("trace printing edn");
}
}
}
class LatchCode {
public void doStuff(final Cont cont) throws RuntimeException, InterruptedException {
System.out.println("Intermediate class start");
try {
Thread.UncaughtExceptionHandler h = new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread th, Throwable ex) {
cont.err.add(ex.getMessage());
}
};
Thread aggregatorThread = new Thread(() -> {
try {
if(cont.err.size() > 0)
return;
System.out.println("AGGREGATOR thread START");
Thread.sleep(3000);
System.out.println("AGGREGATOR thread END");
} catch (Exception e) {
throw new RuntimeException(e);
}
});
CyclicBarrier barrier = new CyclicBarrier(2, aggregatorThread);
AA a = new AA();
BB b = new BB();
CountDownLatch latch = new CountDownLatch(2);
Thread one = new Thread(() -> {
try {
a.doSomething();
} catch (Exception e) {
System.out.println("Exception in 1");
//Thread.currentThread().interrupt();
throw new RuntimeException(e.toString());
} finally {
try {
barrier.await();
} catch (Exception e) {
System.out.println("Exception in 1 finallt");
throw new RuntimeException(e.toString());
} finally {
latch.countDown();
}
}
});
Thread two = new Thread(() -> {
try {
b.doSomething();
} catch (Exception e) {
System.out.println("Exception in 2");
Thread.currentThread().interrupt();
throw new RuntimeException(e);
} finally {
try {
barrier.await();
} catch (Exception e) {
System.out.println("Exception in 2 finallt");
throw new RuntimeException(e);
} finally {
latch.countDown();
}
}
});
one.start();
two.start();
one.setUncaughtExceptionHandler(h);
two.setUncaughtExceptionHandler(h);
latch.await();
} catch (Exception e) {
System.out.println("Exception in caller");
throw new RuntimeException(e);
} finally {
System.out.println("Intermediate class end");
}
}
}
class AA {
public void doSomething() throws Exception {
try {
System.out.println("1 start");
Thread.sleep(1);
throw new Exception("In AA");
} catch (Exception e) {
System.out.println("Exception in AA");
throw new Exception(e.toString());
}
}
}
class BB {
public void doSomething() throws Exception {
try {
System.out.println("2 start");
Thread.sleep(1);
} catch (Exception e) {
System.out.println("Exception in BB");
}
System.out.println("2 end");
}
}
class Cont {
ConcurrentLinkedQueue<String> err = new ConcurrentLinkedQueue<String>();
}
If AA.doStuff() and BB.doStuff() has loger sleeps, then I could Cont.err is not empty and getting into catch block. But whne sleep time is negligible like 1 ms, then if block in main() failed and program is executing as if there is no exception.
So I need calling thread to wait for UncaughtExceptionHandler completion. Could some one help on this.
Thanks in advance
After making exhaustive search, found the following page. Go through the details on how things work in UEH.
https://bugs.openjdk.java.net/browse/JDK-8153487
Excerpt from the above thread for short answer:
There is no guarantee that UncaughtExceptionHandlers have run before awaitTermination returns.
It is a pool thread that sets the state to TERMINATED, so it cannot wait for all pool threads to terminate!
It seems unlikely we can make this better. It seems that relying on the UEH in this way is a poor design
I am trying to use threads to make my program run some parts in parallel and am struggling.
Goal is to process a list of links, urlList through the ImageProcessor().processLink function. I have two problems I am trying to solve:
How do I loop this so it uses N number of threads in the pool, 10 in this case? That is, I want to process 10 links at a time.
The processing function above returns a File, which I need to add to an array, fileList. When it comes to multithreading, how will I handle this?
This is what i've got so far:
ArrayList<String> urlList = new ArrayList<>(Arrays.asList(arr.split("\\r?\\n"))) ;
ArrayList<File> fileList = new ArrayList<>();
ExecutorService executor = Executors.newFixedThreadPool(10);
//process the requested files
for (int i = 0; i < urlList.size(); i++){
Future<File> value = executor.submit(new Callable<File>() {
#Override
public File call(int i) throws IOException {
return new ImageProcessor().processLink(urlList.get(i));
}
});
try {
fileList.add(value.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
Got it working with the following:
ArrayList<String> urlList = new ArrayList<>(Arrays.asList(arr.split("\\r?\\n"))) ;
ArrayList<File> fileList = new ArrayList<>();
ExecutorService executor = Executors.newFixedThreadPool(THREAD_SIZE);
List<Future<File>> futures = new ArrayList<>();
for (int i = 0; i < urlList.size(); i++) {
ImageProcessor proc = new ImageProcessor(urlList.get(i));
final Future<File> future = executor.submit(proc);
futures.add(future);
}
try {
executor.awaitTermination(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < futures.size(); i++)
{
Future<File> result = futures.get(i);
try {
fileList.add(result.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
executor.shutdown();
while (!executor.isTerminated()) { }
System.out.println("Finished all threads");
I am using the below code in a java application.It spawns 3 worker threads. What I need is that if one thread fails (throws an unhandled exception from run)other threads should continue execution. If I call executor.shutdown() as below it is terminating the other threads(no new tasks are accepted).One of the options that I was thinking was to have a counter on the ExecutionException catch block and call shutdown only when counter==numConsumers. Is there a better way to do this?
public void execute() {
int numConsumers = Integer.parseInt(configs.getSINK_NUMBER_OF_CONSUMERs());
Future<?> future=null;
log.info("Creating {} consumers",numConsumers);
List<String> topics = Arrays.asList(configs.getTOPIC_NAME());
ExecutorService executor = Executors.newFixedThreadPool(numConsumers);
final List<SinkConsumer> consumers = new ArrayList<>();
for (int i = 0; i < numConsumers; i++) {
consumer = new SinkConsumer(UUID.randomUUID().toString(),topics,configs);
consumers.add(consumer);
future = executor.submit(consumer);
}
try {
future.get();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (ExecutionException e) {
executor.shutdown();
}
}
I'm pretty new to Multithreading in java but am totally stumped about why this isn't behaving as I want it to.
I have a Producer-Consumer wherein I have
private void produceConsume() {
try {
Thread producer = new Thread(new Runnable() {
public void run() {
try {
produce();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
completedProduce = true;
}
}
private void produce() throws InterruptedException {
synchronized (this) {
while (queue.size() == capacity) {
wait();
}
try(InputStream is = new FileInputStream(file)) {
queue.add("hello");
} catch (IOException e) {
LOG.error("Error doing stream stuff: " + e.getMessage(), e);
}
notify();
}
}
});
producer.start();
List<Thread> consumers = new ArrayList<>();
for (int i = 0; i < noOfThreads; i++) {
Thread consumer = new Thread(new Runnable() {
#Override
public void run() {
try {
consume();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void consume() throws InterruptedException {
while (queue.size() > 0 || !completedProduce) {
synchronized (this) {
while (queue.size() == 0 && !completedProduce) {
wait();
}
String s = queue.poll();
System.out.println(s);
}
notify();
}
}
}
});
consumer.start();
consumers.add(consumer);
}
for (Thread t : consumers) {
t.join();
}
producer.join();
} catch (Exception e) {
LOG.error("InterruptedException e: " + e.getMessage(), e);
} finally {
LOG.info("We are done with this file!");
}
}
Now, I've noticed that all functionality changes based on where I put my producer.join() statement. For example, if I put producer.join() right after producer.start() then everything works - but the number of threads has no impact on runtime. This makes sense as I'm slowed down drastically by how long it takes to produce and so the longest task wins out.
However, if I put producer.join() where it is in the example provided (I do the join when I do the join for the consumers) then everything just stops running before the producer actually finishes. As in, the program stalls after the first thing is consumed, waiting for something, but the thread never dies.
How do I make it so that things run correctly and nothing stalls waiting for another process to finish?
Thanks in advance,
I have the following code in a command line application. Once the loop completes, my app is still running. Why is it not shutting down. From the logs, I can see that endIndex has reached. But the app is still running?
Executor exec = Executors.newFixedThreadPool(4);
for (int i = startIndex; i <= endIndex; i++) {
final String spURL = urlPart + i;
Runnable requestHandler = new Runnable() {
#Override
public void run() {
try {
getImageForURL(spURL, 0);
} catch (IOException ex) {
} catch (Exception ex) {
}
}
};
exec.execute(requestHandler);
}
Try this
ExecutorService e = Executors.newFixedThreadPool(4);
...
e.shutdown();
You need to shutdown the executors after the loop (ideally in a finally block):
exec.shutdown() or exec.shutdownNow()