Java Executor Service waiting for all tasks to complete [duplicate] - java

This question already has answers here:
How to wait for all threads to finish, using ExecutorService?
(27 answers)
Closed 4 years ago.
I am using executor service to run my 10 tasks with 2 tasks at a time.
ExecutorService executor = Executors.newFixedThreadPool(2);
for (int i = 0; i < 10; i++) {
String name = "NamePrinter " + i;
Runnable runner = new TaskPrint(name, 1000);
System.out.println("Adding: " + name + " / " + 1000);
executor.execute(runner);
}
How can I wait for all tasks to complete

Use java 8 CompleteableFuture with join method to wait:
ExecutorService executor = Executors.newFixedThreadPool(2);
CompletableFuture[] futures = new CompletableFuture[10];
for (int i = 0; i < 10; i++) {
String name = "NamePrinter " + i;
Runnable runner = new TaskPrint(name, 1000);
System.out.println("Adding: " + name + " / " + 1000);
futures[i] = CompletableFuture.runAsync(runner, executor);
}
CompletableFuture.allOf(futures).join(); // THis will wait until all future ready.

Assign your callables to futures and check that you can get results from each future.
Future future = workerExecutor.submit(new Callable() {
#Override
public Object call() throws Exception {
try {
System.out.println("MyItemTree.TimedRunnable");
ReturnInterface returnInterface = (ReturnInterface) commandInterface.call();
returnInterface.submitResult();
} catch (Exception ex) {
ex.printStackTrace();
throw new RuntimeException(ex);
}
return null;
}
});
try {
Object get = future.get();
} catch (InterruptedException | ExecutionException ex) {
Throwable cause = ex.getCause();
ex.printStackTrace();
cause.printStackTrace();
Throwable cause1 = cause.getCause();
if (cause1 instanceof CommandInterfaceException) {
System.out.println("[MyItemTree].scheduleTask Cause 1= COMMANDINTERFACE EXCEPTION");
this.componentInterface.getAlertList().addAlert(((CommandInterfaceException) cause1).getResolverFormInterface());
}
}
}

Related

Streaming data on same outputStream in multiple threads

I am creating a spring boot application which connects to multiple REST services and write the responses on outputStream.
I am also using multiple threads to call the REST services.
public ResponseEntity<StreamingResponseBody> startBombing(Request request) {
int numberOfThreads = request.getConfig().getNumberOfThreads() ==0?5:request.getConfig().getNumberOfThreads();
long requestPerThread = request.getConfig().getRequestPerThread() ==0 ? 100: request.getConfig().getRequestPerThread();
StreamingResponseBody responseBody = response -> {
for (int i = 1; i <= numberOfThreads; i++) {
int finalI = i;
Runnable r1 = () -> {
try {
for (int j = 1; j <= requestPerThread; j++) {
HttpRequest req = createRequest(request.getHttpRequest());
Object res = doRequest(req);
System.out.println("Thread number: " + finalI + ": " + "call number: " + j + "TimeStamp: " + System.currentTimeMillis() + ":::: RESPONSE: " + res);
response.write(("Thread number: " + finalI + ": " + "call number: " + j + "TimeStamp: " + System.currentTimeMillis() + ":::: RESPONSE: " + res).getBytes());
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
};
Thread t1 = new Thread(r1);
t1.start();
}
};
return ResponseEntity.ok()
.contentType(MediaType.TEXT_PLAIN)
.body(responseBody);
}
No data is printed on the output stream.
Any clue how to reuse same outputStream in muliple threads
Wait for all threads to finish before exiting lambda (as it will close the output for you)
StreamingResponseBody responseBody = response -> {
CountDownLatch latch=new CountDownLatch(numberOfThreads);
for (int i = 1; i <= numberOfThreads; i++) {
int finalI = i;
Runnable r1 = () -> {
try {
//ireelevant code
} finally{
latch.countDown(); // decrease latch counter
}
};
Thread t1 = new Thread(r1);
t1.start();
}
latch.await(); // wait for latch to count down to 0 + add error handling and return value
};

Java how to call a method in parallel passing chunked data

I have an API call that can only accept 5 subrequests at a time. So I need to chunkify if more than 10 subrequests come in and then send them in parallel as per the SLA.
Below is a nonparallel chunkified code and I am looking to parallelize this call invokeService(bulkRequestChunk)
int BULK_SUBREQUEST_SIZE = 5;
// infoRequestList size = 7
for (int i = 0; i < numOfSubRequests; i += BULK_SUBREQUEST_SIZE) {
List<InfoRequest> infoRequestChunk;
if (i + BULK_SUBREQUEST_SIZE >= numOfSubRequests) {
infoRequestChunk = infoRequestList.subList(i, numOfSubRequests);
} else {
infoRequestChunk = infoRequestList.subList(i, i + BULK_SUBREQUEST_SIZE);
}
BulkRequest bulkRequestChunk = new BulkRequest();
bulkRequestChunk.setRequests(infoRequestChunk);
BulkResponse bulkResponseChunk = invokeService(bulkRequestChunk);
// output list to capture all chunked requests
bulkResponseList.add(bulkResponseChunk);
}
Use an ExecutorService and submit it tasks to run in parallel:
ExecutorService execServ = Executors.newFixedThreadPool(numThreads);
final List<BulkResponse> bulkResponseList = new ArrayList<>();
int BULK_SUBREQUEST_SIZE = 5;
for (int i = 0; i < numOfSubRequests; i += BULK_SUBREQUEST_SIZE) {
List<InfoRequest> infoRequestChunk;
if (i + BULK_SUBREQUEST_SIZE >= numOfSubRequests) {
infoRequestChunk = infoRequestList.subList(i, numOfSubRequests);
} else {
infoRequestChunk = infoRequestList.subList(i, i + BULK_SUBREQUEST_SIZE);
}
BulkRequest bulkRequestChunk = new BulkRequest();
bulkRequestChunk.setRequests(infoRequestChunk);
execServ.submit(() -> {
BulkResponse bulkResponseChunk = invokeService(bulkRequestChunk);
bulkResponseList.add(bulkResponseChunk);
});
}
execServ.shutdown();
try {
execServ.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
} catch (InterruptedException e) {
}

ReentrantLock tryLock(timeout,timeUnit) doesn't work as expected

I have some confuse about ReentrantLock tryLock(timeout,timeUnit) method , when
running below code it seems tryLock timeout until the previous thread end,could anyone explains this?
public class MyService2 {
public ReentrantLock lock = new ReentrantLock();
public void waitMethod() {
try {
System.out.println(System.currentTimeMillis() + " " + Thread.currentThread().getName() + " enter ");
boolean b = lock.tryLock(2, TimeUnit.SECONDS);
if (b) {
System.out.println(System.currentTimeMillis() + " lock begin:" + Thread.currentThread().getName());
for (int i = 0; i < Integer.MAX_VALUE / 10; i++) {
Math.random();
}
System.out.println(System.currentTimeMillis() + " lock end " + Thread.currentThread().getName());
return;
}
System.out.println(System.currentTimeMillis() + " " + Thread.currentThread().getName() + " got no lock end ");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
public static void main(String[] args) throws InterruptedException {
MyService2 myService2 = new MyService2();
Runnable runnable = myService2::waitMethod;
Thread thread1 = new Thread(runnable);
thread1.setName("T1");
thread1.start();
TimeUnit.MILLISECONDS.sleep(10);
Thread thread2 = new Thread(runnable);
thread2.setName("T2");
thread2.start();
}
after running this code ,the result is like that
1555343172612 T1 enter
1555343172613 lock begin:T1
1555343172627 T2 enter
1555343179665 lock end T1
1555343179665 T2 got no lock end
my question is why thread T2 doesn't timeout in 2s rather than waiting until thread T1 ends?
BUT I just found:
if replace Math.random() with TimeUnit.SECONDS.sleep(1) for example ,it works fine.
if run in debug mode ,it works fine too.
Here is an alternate which has a number modifications:
First, cleanups. Clearer names. Less intrusive logging. Relative time values.
Second, the 0.1s sleep between the launch of the two compute threads is moved into each of the threads. That more clearly gives precedence to the thread which launches the compute threads.
Third, the launch thread has joins with the compute threads. That is to tie the conclusion of the computation to the launch thread. In the original code, there is no management of the compute threads after they have been launched. If the compute threads are intended to be unmanaged, that needs to be documented.
Fourth, the entire launch thread plus two compute threads structure is replicated. That is to place give the structure a more realistic runtime environment, and, to present the different behaviors of the structure together in a single view.
A theme to the modifications is to provide clarity, both to the intended behavior of the program, and to the actual behavior (as viewed through the logging output). The goal is to provide maximal clarity to these.
An additional modification is recommended, which is to put the log statements into a cache, then display the collected log lines after all of the computation cells have completed. That removes behavior changes caused by the log statements, which are often considerable.
package my.tests;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
public class LockTest {
private static long initialTime;
protected static void setInitialTime() {
initialTime = System.currentTimeMillis();
}
public static long getInitialTime() {
return initialTime;
}
public static final int CELL_COUNT = 10;
public static void main(String[] args) {
setInitialTime();
System.out.println("Beginning [ " + Integer.toString(CELL_COUNT) + " ] computation cells");
Thread[] cellThreads = new Thread[CELL_COUNT];
for ( int cellNo = 0; cellNo < CELL_COUNT; cellNo++ ) {
final String cellNoText = Integer.toString(cellNo);
Runnable computeCell = () -> {
(new LockTest(cellNoText) ).compute();
};
Thread cellThread = new Thread(computeCell);
cellThreads[cellNo] = cellThread;
}
// Start them all up ...
for ( Thread cellThread : cellThreads ) {
cellThread.start();
}
// Then wait for them all to finish ...
for ( Thread cellThread : cellThreads ) {
try {
cellThread.join();
} catch ( InterruptedException e ) {
System.out.println("Unexpected interruption: " + e.getMessage());
e.printStackTrace();
}
}
System.out.println("Completed [ " + Integer.toString(CELL_COUNT) + " ] computation cells");
}
//
public LockTest(String cellName) {
this.cellName = cellName;
}
private final String cellName;
public String getCellName() {
return cellName;
}
// Logging ...
public String formatTime(long timeMs) {
return String.format("%12d (ms)", new Long(timeMs));
}
public long getRelativeTime(long currentTime) {
return currentTime - getInitialTime();
}
public String formatRelativeTime(long timeMs) {
return String.format(
"%12d %8d (ms)",
new Long(timeMs),
new Long( timeMs - getInitialTime() ));
}
public void log(String methodName, String message) {
long timeMs = System.currentTimeMillis();
String threadName = Thread.currentThread().getName();
System.out.println(
formatRelativeTime(timeMs) + ": " +
methodName + ": " +
threadName + ": " + message);
}
//
public void compute() {
log("compute", "ENTER: " + getCellName());
Runnable computation = () -> {
guardedComputation(
100L, 0, // Pause 0.1s before attempting the computation
1, TimeUnit.SECONDS, // Try to obtain the computation lock for up to 1.0s.
Integer.MAX_VALUE / 60 ); // Run this many computations; takes about 2s; adjust as needed
};
Thread computer1 = new Thread(computation);
computer1.setName( getCellName() + "." + "T1");
Thread computer2 = new Thread(computation);
computer2.setName( getCellName() + "." + "T2");
// Run two sets of computations:
//
// Each will pause for 0.1s before performing the computations.
//
// Performing computations requires a computation lock; wait up to 2.0s
// to acquire the lock.
computer1.start();
computer2.start();
try {
computer1.join();
} catch ( InterruptedException e ) {
System.out.println("Unexpected interruption: " + e.getMessage());
e.printStackTrace();
return;
}
try {
computer2.join();
} catch ( InterruptedException e ) {
System.out.println("Unexpected interruption: " + e.getMessage());
e.printStackTrace();
return;
}
log("compute", "RETURN: " + getCellName());
}
// Computation locking ...
private final ReentrantLock computationLock = new ReentrantLock();
public boolean acquireComputationLock(long maxWait, TimeUnit maxWaitUnit) throws InterruptedException {
return computationLock.tryLock(maxWait, maxWaitUnit);
}
public void releaseComputationLock() {
if ( computationLock.isHeldByCurrentThread() ) {
computationLock.unlock();
}
}
//
public void guardedComputation(
long pauseMs, int pauseNs,
long maxWait, TimeUnit maxWaitUnit, int computations) {
String methodName = "guardedComputation";
log(methodName, "ENTER");
try {
Thread.sleep(pauseMs, pauseNs);
} catch ( InterruptedException e ) {
System.out.println("Unexpected interruption: " + e.getMessage());
e.printStackTrace();
return;
}
try {
boolean didLock;
try {
didLock = acquireComputationLock(maxWait, maxWaitUnit);
} catch ( InterruptedException e ) {
System.out.println("Unexpected interruption: " + e.getMessage());
e.printStackTrace();
return;
}
String computationsText = Integer.toString(computations);
if ( didLock ) {
log(methodName, "Starting computations: " + computationsText);
for ( int computationNo = 0; computationNo < computations; computationNo++ ) {
Math.random();
}
log(methodName, "Completed computations: " + computationsText);
} else {
log(methodName, "Skipping computations: " + computationsText);
}
} finally {
releaseComputationLock();
}
log(methodName, "RETURN");
}
}

Java for loop of threads starting together (almost same time)

With this code:
final CyclicBarrier gate = new CyclicBarrier(2);
Thread t1 = new Thread() {
public void run() {
try {
gate.await();
for (int i = 0; i < 1000; i++) {
System.out.println("F1:" + i);
}
} catch (InterruptedException | BrokenBarrierException ex) {
Logger.getLogger(TestFor.class.getName()).log(Level.SEVERE, null, ex);
}
}
};
Thread t2 = new Thread() {
public void run() {
try {
gate.await();
for (int i = 0; i < 1000; i++) {
System.out.println("F2:" + i);
}
} catch (InterruptedException | BrokenBarrierException ex) {
Logger.getLogger(TestFor.class.getName()).log(Level.SEVERE, null, ex);
}
}
};
t1.start();
t2.start();
I am able to start the 2 threads. Now I need more than 2 threads, lets say 50. The only changing parameter in those for loops is System.out.println("F2:" + i); as FX where X is the number of the thread.
Is there any way of making those 50 threads inside a for loop ?
You could use something like
List<Thread> tList = new ArrayList<Thread>();
for(int i = 0; i < 50; i++) {
final int id = i;
tList.add(new Thread() {
public void run() {
try {
gate.await();
for (int k = 0; k < 1000; k++) {
System.out.println("F" + id + ":" + k);
}
}
catch (InterruptedException | BrokenBarrierException ex) {
Logger.getLogger(TestFor.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
To start all of them you simply
for(Thread t : tList)
t.start();
If it is really about time and maybe your code for a single Thread increases this will first initialize all of them and start them directly after each other, so you don't need to think about the time you actually need to initialize them.
You mean, similar to this?
for (int j = 0; j < 50; ++j) {
new Thread() {
public void run() {
try {
gate.await();
for (int i = 0; i < 1000; i++) {
System.out.println("F" + j + ":" + i);
}
} catch (InterruptedException | BrokenBarrierException ex) {
Logger.getLogger(TestFor.class.getName()).log(Level.SEVERE, null, ex);
}
}
}.start();
}
If you need n threads to start at the same time, you could convert your Runnables into Callables using Executors.callable() and then using the invokeAll() method on an ExecutorService.
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html#invokeAll(java.util.Collection)
An example is provided at ExecutorService.invokeAll does NOT support collection of runnable task

Why do these threads return an incorrect calculation? [duplicate]

This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 8 years ago.
I am quite new to concurrent programming and I am enjoying it so far :)! However I just realized how tricky concurrent programming.
I have multiple threads which perform their own computations. Each thread operates on a certain variable and returns a result, however the result returned is incorrect.
This class performs the thread calculations:
public class SharedDataThread extends Thread {
private SharedData mySharedData;
private String myThreadName;
private static long testVariable = 0;
// Setup the thread
SharedDataThread(String name, SharedData sharedstuff) {
super(name);
mySharedData = sharedstuff;
myThreadName = name;
}
public void run() {
System.out.println(myThreadName + " is running");
Thread me = Thread.currentThread(); // get a ref to the current thread
if (me.getName() == "myThread1") {
try {
sleep(2000);
mySharedData.acquireLock();
System.out.println(me.getName()
+ " is performing computations!");
testVariable = testVariable + 20;
testVariable = testVariable * 5;
testVariable = testVariable / 3;
System.out.println(me.getName() + " modified the value to : "
+ testVariable + "\n");
sleep(2000);
mySharedData.releaseLock();
} catch (InterruptedException e) {
System.err.println("Failed to get lock when reading:" + e);
}
} else if (me.getName() == "myThread2") {
try {
sleep(2000);
mySharedData.acquireLock();
System.out.println(myThreadName
+ " is performing computations!");
testVariable = testVariable - 5;
testVariable = testVariable * 10;
testVariable = (long) (testVariable / 2.5);
System.out.println(me.getName() + " modified the value to : "
+ testVariable + "\n");
sleep(2000);
mySharedData.releaseLock();
} catch (InterruptedException e) {
System.err.println("Failed to get lock when reading:" + e);
}
} else if (me.getName() == "myThread3") {
try {
sleep(2000);
mySharedData.acquireLock();
System.out.println(me.getName()
+ " is performing computations!");
testVariable = testVariable - 50;
testVariable = testVariable / 2;
testVariable = testVariable * 33;
System.out.println(me.getName() + " modified the value to : "
+ testVariable + "\n");
sleep(2000);
mySharedData.releaseLock();
} catch (InterruptedException e) {
System.err.println("Failed to get lock when reading:" + e);
}
} else {
try {
sleep(2000);
mySharedData.acquireLock();
System.out.println(me.getName()
+ " is performing computations!");
testVariable = testVariable * 20;
testVariable = testVariable / 10;
testVariable = testVariable - 1;
System.out.println(me.getName() + " modified the value to : "
+ testVariable + "\n");
sleep(2000);
mySharedData.releaseLock();
} catch (InterruptedException e) {
System.err.println("Failed to get lock when reading:" + e);
}
}
System.out.println("The final result of the variable is "
+ testVariable);
}
}
The threads are executed in another class with its own main thread of execution:
public class SharingExample {
public static void main(String[] args) {
SharedData mySharedData = new SharedData();
SharedDataThread myThread1 = new SharedDataThread("myThread1", mySharedData);
SharedDataThread myThread2 = new SharedDataThread("myThread2", mySharedData);
SharedDataThread myThread3 = new SharedDataThread("myThread3", mySharedData);
SharedDataThread myThread4 = new SharedDataThread("myThread4", mySharedData);
// Now start the threads executing
myThread1.start();
myThread2.start();
myThread3.start();
myThread4.start();
}
}
the SharedData class is just a class for implementing locks and such.
public class SharedData {
private boolean accessing=false; // true a thread has a lock, false otherwise
private int threadsWaiting=0; // number of waiting writers
// attempt to acquire a lock
public synchronized void acquireLock() throws InterruptedException{
Thread me = Thread.currentThread(); // get a ref to the current thread
System.out.println(me.getName()+" is attempting to acquire a lock!");
++threadsWaiting;
while (accessing) { // while someone else is accessing or threadsWaiting > 0
System.out.println(me.getName()+" waiting to get a lock as someone else is accessing...");
//wait for the lock to be released - see releaseLock() below
wait();
}
// nobody has got a lock so get one
--threadsWaiting;
accessing = true;
System.out.println(me.getName()+" got a lock!");
}
// Releases a lock to when a thread is finished
public synchronized void releaseLock() {
//release the lock and tell everyone
accessing = false;
notifyAll();
Thread me = Thread.currentThread(); // get a ref to the current thread
System.out.println(me.getName()+" released a lock!");
}
}
Where is the problem here?
Your 'testVariable' should be marked as 'volatile'. See this topic for more information: Volatile Vs Static in java.

Categories

Resources