There is a multithreaded code that works correctly using system threading:

// Main thread Thread producer = new Thread(resultDAO); Thread consumer = new Thread(resultsLoader); producer.start(); // start first added thread consumer.start(); // start second added thread try { consumer.join(); } catch (InterruptedException e) { e.printStackTrace(); } 

It is necessary to alter this code using java.util.concurrent , i.e. with software organization multithreading. Posted by:

  // Main thread Thread producer = new Thread(resultDAO); Thread consumer = new Thread(resultsLoader); ExecutorService threadExecutor = Executors.newCachedThreadPool(); threadExecutor.execute(producer); threadExecutor.execute(consumer); threadExecutor.shutdown(); while (!threadExecutor.isShutdown()) { System.out.println("Main THREAD WAIT"); try { threadExecutor.wait(100); } catch (InterruptedException e) { 

but the main thread continues to work when the subflows that have not completed their work continue, and then it conflicts with access to the database with the consumer . What am I doing wrong? How do java.util.concurrent make an analogue join() ?

  • It would be necessary to secure access to the database, and not try to get away from the possibility of conflict threads. - Gorets
  • I agree, if you focus on the real application, but for now the question is precisely this - how to stop the main thread until the sub-flows are completely executed? - rvm

2 answers 2

As I understand it, one thread is writing to the database, and the second one is trying to read at the same time? If yes, then, in my opinion, this is not the right approach. These actions should go consistently. If you want to suspend a thread that runs the other two (producer, consumer), then you can try this:

 while (true) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } int active = taskExecutor.getActiveCount(); if (active == 0) { taskExecutor.shutdown(); return; } } 

taskExecutor is a ThreadPoolTaskExecutor ;

A class that runs with taskExecutor should implement the Runnable interface. It should also be patched like this: @Scope(value="prototype") . Example:

 @Scope(value="prototype") public class RunnableService implements Runnable{ @Override public void run() { //TODO } } 

Runs like this:

 RunnableService task = ContextHolder.getBean(RunnableService.class); taskExecutor.execute(task); 
  • The first stream reads data from the file and is transmitted through the buffer queue to the second stream, which overloads the data into the database. For the implementation of this operation, I need to suspend the flow of MAIN until the sub-streams are finished. - rvm
  • if I understand you correctly, the option that I proposed should come to you. Main will “sleep” until the subflows are executed. Only one amendment: if Main should do something else after executing the subflows, then instead of return we write the code. - pirateweter
  • Thread.sleep (1000) is somehow ugly. Probably it is better to look for a method of waiting for some suitable events. IMHO in java.util.concurrent should be such a mechanism (s). It is necessary to read the dock carefully. - avp
  • @avp suggest :) - pirateweter
  • Immediately in the dock I saw the method boolean awaitTermination (long timeout, TimeUnit unit) throws InterruptedException not that? - By the way, the .wait () you are using IMHO is inherited from Object. It will only work on .notify () on this object (you have ExecutorService threadExecutor). And who will this .notify () call? - avp

Correct answer:

 Thread producer = new Thread(reader); Thread consumer = new Thread(resultsLoader); ExecutorService threadExecutor = Executors.newCachedThreadPool(); threadExecutor.execute(producer); threadExecutor.execute(consumer); threadExecutor.shutdown(); try { threadExecutor.awaitTermination(5, TimeUnit.SECONDS); }catch (InterruptedException e) { e.printStackTrace(); } 

Thanks @avp pushed!