I try to make multithreading program on Java print results that returned finished threads.
The thing is, when i run this code it simply gets stuck on second value that was in queue:
System.out.println("[!] Creaing pool");
int max_threads = 50;
ExecutorService threadPool = Executors.newFixedThreadPool(max_threads);
CompletionService<String> taskCompletionService =
new ExecutorCompletionService<String>(threadPool);
String url;
while(our_file.hasNext()){
url = our_file.next();
if (url.length()>0){
futures.add(
taskCompletionService.submit(
new GoGo(url)
)
);
}
int total_tasks = futures.size();
while(total_tasks>0){
for (int i=0; i<futures.size(); i++){
try{
Future result = taskCompletionService.poll();
if(result!=null && result.isDone()){
System.out.println(result.get());
total_tasks--;
}
}
catch (InterruptedException e) {
// Something went wrong with a task submitted
System.out.println("Error Interrupted exception");
e.printStackTrace();
} catch (ExecutionException e) {
// Something went wrong with the result
e.printStackTrace();
System.out.println("Error get() threw exception");
}
}
}
}
threadPool.shutdown();
try {
threadPool.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
}
catch (InterruptedException e ) {
}
...
class GoGo implements Callable{
private String url;
public GoGo(String received_url){
this.url = received_url;
}
public String call(){
String URL = this.url;
return url;
}
}
output is like this:
[!] Creaing pool
http://www.www1.com/
http://www.www2.ch/
and at this point program just stucks.
I tried to move loop that iterates futures array out of main loop that submits threads, and it worked fine, but in case if i will go through very large file i need real-time output.
Please help me figure out where is the bottleneck, I was unable to find any suitable piece of code that using non-blocking poll() method from CompletionService.
Thanks for any answer or reference.
The problem is you are trying to do two things simultaneously (submit work, and read work results) in one thread.
That doesn't make sense - for simultaneous tasks, you need multiple threads.
So create another thread to read the results. Or another thread to submit the tasks. It doesn't matter which way you do it; either way, you end up with 2 threads instead of one.
Thanks to Robin Green for advice, putting future harvester class to separate thread solved the problem! So, i just start the endless loop thread that pops argument with poll() check if the popped future object indicates that thread isDone() and write output. And after shutting down the fixedThreadPool, output writer class is stopped. Here's the code (except the GoGo class):
public class headScanner {
public static List<Future<String>> gloabal_futures = new ArrayList<Future<String>>();
public static void main(String args[]){
Scanner our_file = null;
ArrayList<String> our_urls = new ArrayList<String>();
List<Future<String>> futures = new ArrayList<Future<String>>();
ArrayList<String> urls_buffer = new ArrayList<String>();
try {
our_file = new Scanner (new File ("list.txt"));
}
catch(IOException e){
System.out.println("[-] Cant open the file!");
System.exit(0);
}
System.out.println("[!] Creaing pool");
int max_threads = 50;
ExecutorService threadPool = Executors.newFixedThreadPool(max_threads);
CompletionService<String> taskCompletionService =
new ExecutorCompletionService<String>(threadPool);
String url;
Thread result_thread = new Thread(new ResultHarvester(futures.size(), taskCompletionService));
result_thread.start();
while(our_file.hasNext()){
url = our_file.next();
if (url.length()>0){
futures.add(
taskCompletionService.submit(
new GoGo(url)
)
);
}
}
threadPool.shutdown();
try {
threadPool.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
}
catch (InterruptedException e ) {
}
result_thread.stop();
}
}
class ResultHarvester implements Runnable {
private int size;
private CompletionService<String> all_service;
public ResultHarvester (int size, CompletionService<String> service){
this.size = size;
this.all_service = service;
}
public void run(){
int future_size = 1;
CompletionService<String> this_service = this.all_service;
while(true){
Future result = this_service.poll();
try {
if(result!=null && result.isDone()){
String output = result.get().toString();
if(output.length()>1){
System.out.println(output);
}
}
}
catch (InterruptedException e) {
// Something went wrong with a task submitted
System.out.println("Error Interrupted exception");
e.printStackTrace();
} catch (ExecutionException e) {
// Something went wrong with the result
e.printStackTrace();
System.out.println("Error get() threw exception");
}
}
}
}
Related
Recently I begin to learn concurrency based on Java, I run the following code on windows (jdk 11)
import java.util.*;
import java.util.concurrent.*;
class TaskWithResult implements Callable<String>{
private int id;
public TaskWithResult(int id){
this.id = id;
}
public String call(){
return "Result of TaskWithResult "+id;
}
}
public class TestCallable{
public static void main(String[] args){
ExecutorService exec = Executors.newCachedThreadPool();
ArrayList<Future<String>> results =
new ArrayList<Future<String>>();
for(int i = 0;i<10;i++){
results.add(exec.submit(new TaskWithResult(i)));
for(Future<String> fs:results){
try{
System.out.println(fs.get());
}catch(InterruptedException e){
System.out.println(e);
return;
}catch(ExecutionException e){
System.out.println(e);
}finally{
exec.shutdown();
}
}
}
}
}
The sanme Exception occurs everytime I run it:
\\output:
Result of TaskWithResult 0
Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask#380fb434[Not completed, task = me.rexjz.a.TaskWithResult#21bcffb5] rejected from java.util.concurrent.ThreadPoolExecutor#3cda1055[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 1]
at java.base/java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2055)
at java.base/java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:825)
at java.base/java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1355)
at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:140)
at javaBin/me.rexjz.a.TestCallable.main(TestCallable.java:22)
The code is excerpted from Thinging in Java(4th),I initially guess the implicit thread which drives main() execute shutdown() before all the tasks are submitted because the first task is succeessfully executed and the Exeception information indicates that pool size= 1, but it is impossible because everything in main() is sequentially executed. All the Callable objects should be submitted before shutdown.
Then I change the type of ThreadPool to Executors.newFixedThreadPool(10), the Exception stil occured and the pool size is still 1.
How did this happen?
If you look at your for loops a little more closely you'll see the problem (especially once the code is conventionally indented):
for (int i = 0; i < 10; i++) {
results.add(exec.submit(new TaskWithResult(i)));
for (Future<String> fs : results) {
try {
System.out.println(fs.get());
} catch (InterruptedException e) {
System.out.println(e);
return;
} catch (ExecutionException e) {
System.out.println(e);
} finally {
exec.shutdown();
}
}
}
Notice that the for loop which queries each Future is nested within the for loop which submits the tasks. That means you submit one task, wait for the result, shutdown the executor, and then attempt to submit another task. The following should fix your problem:
for (int i = 0; i < 10; i++) {
results.add(exec.submit(new TaskWithResult(i)));
}
executor.shutdown(); // shutdown() allows already-submitted tasks to execute
for (Future<String> fs : results) {
try {
System.out.println(fs.get());
} catch (InterruptedException e) {
e.printStackTrace();
return;
} catch (ExecutionException e) {
e.printStackTrace();
}
}
I moved the executor.shutdown() call since that only needs to happen once, after you've submitted the last task. Of course, if you're going to keep reusing the executor then you would not want to shut it down.
I also changed System.out.println(e) to e.printStackTrace(). It's typically better to print the stack trace rather than just the exception type and message (which is what Throwable#toString() returns, by default). It may not be obvious in a short program like your example, but the stack trace is extremely valuable in more complicated applications since it points you directly to where the exception was thrown. See What is a stack trace, and how can I use it to debug my application errors? for more information.
package com.springboot.testapplication;
import java.util.*;
import java.util.concurrent.*;
class TaskWithResult implements Callable<String> {
private int id;
public TaskWithResult(int id) {
this.id = id;
}
public String call() {
return "Result of TaskWithResult " + id;
}
}
public class TestCallable {
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
ArrayList<Future<String>> results = new ArrayList<Future<String>>();
for (int i = 0; i < 10; i++) {
results.add(exec.submit(new TaskWithResult(i)));
}
for (Future<String> fs : results) {
try {
System.out.println(fs.get());
} catch (InterruptedException e) {
System.out.println(e);
return;
} catch (ExecutionException e) {
System.out.println(e);
} finally {
exec.shutdown();
}
}
}
}
I have the following class, I usually run about 10 threads of it
public class MyClass implements Runnable {
private volatile Device device = null;
public MyClass(Device device) {
this.device = device;
}
#Override
public void run() {
while (true) { // <--- I do know that the "true" has to be changed to a Boolean
try {
Worker worker = new Worker();
worker.work();
System.out.println("Waiting 6 seconds!");
Thread.sleep(6 * 1000);
System.out.println("------------------------------------");
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println("Thread in program ended!");
}
}
and in my main I start the threads like this
for (int i = 0; i < 2; i++) {
(new Thread(new MyClass())).start();
}
This is a console based program. What is the most reliable way to end the program? I think the best way would be to change while (true) to while (Boolean) and somehow change that Boolean for all threads, then when the loop ends, the program will end gracefully.
Here i'm ending it by waiting for a user input but you can change it to fire the stop method from anywhere
public static void main(String[] args) {
List<MyClass> myThreads = new ArrayList<>();
for (int i = 0; i < 2; i++) {
MyClass myClass = new MyClass();
Thread t = new Thread(myClass);
t.start();
myThreads.add(myClass);
}
Scanner in = new Scanner(System.in);
in.next();
for(MyClass t : myThreads){
t.stop();
}
}
class MyClass implements Runnable {
private Boolean flag;
public MyClass() {
this.flag = true;
}
#Override
public void run() {
while (flag) { // <--- I do know that the "true" has to be changed to a Boolean
try {
System.out.println("Waiting 6 seconds!");
Thread.sleep(6 * 1000);
System.out.println("------------------------------------");
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println("Thread in program ended!");
}
public void stop(){
this.flag = false;
} }
The easy way would be to store all your threads in a set and make loop joining them at the end.
Be aware that this is not the most ortodox neither the most efficient way to do this.
In your main:
HashSet<Thread> threads = new HashSet();
for (int i = 0; i < 2; i++) {
Thread t = new Thread(new MyClass());
threads.add(t);
t.start();
}
for (Thread thread: threads) {
thread.join();
}
some more material
The following code uses an executor service to fix the number of threads that run at any time, it provides a Future object that also tells you when your thread has shutdown gracefully. They share a shutdown object as well. This offers you a bit more flexibility as the executor service can let you decide how many threads run at any one time gracefully.
First lets created a shared shutdown object that will notify all the threads it is time to shut down. There will be one instance of this and each thread will have a copy.
public static class Shutdown {
private boolean running;
public void shutdown() {
this.running = false;
}
public boolean isRunning() {
return running;
}
}
Next let me just create a dummy thread that does nothing more than sleep forever while it is running. Obviously you can simply replace this with your own thread to do something useful.
public static class MyClass implements Runnable {
final Shutdown shutdown;
public MyClass(Shutdown shutdown) {
this.shutdown = shutdown;
}
#Override
public void run() {
while (shutdown.isRunning()) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
System.out.println("Did not gracefully shut down");
}
}
System.out.println("Thread in program ended!");
}
}
}
Now for the main class which will run everything, this is where the magic happens.
public class Main {
public static void main(String[] args) {
//run exactly 10 threads at a time
ExecutorService executorService = Executors.newFixedThreadPool(10);
//this is how we shut it down
Shutdown globalShutdown = new Shutdown();
//start up the 10 threads
List<Future<?>> futures = new ArrayList<>();
for(int i = 0; i< 10; i++)
futures.add(executorService.submit(new MyClass(globalShutdown)));
//gracefully shut them down
globalShutdown.shutdown();
try {
//wait for them all to shutdown
for(Future<?> future : futures)
future.get();
} catch (InterruptedException e) {
throw new IllegalStateException("This should never happen");
} catch (ExecutionException e) {
throw new IllegalStateException("This should never happen");
}
//everything got shutdown!
}
in practice however you probably also want to handle the case where your thread may not end gracefully due to a bug. Rather than stall forever you might want to add a timeout and if that timeout is exceeded then simply forcibly terminate all remaining threads. To do that replace the above try-catch block with this.
try {
//wait for them all to shutdown
boolean timedout = false;
for(Future<?> future : futures) {
if( !timedout ) {
try {
future.get(30, TimeUnit.SECONDS);
} catch (TimeoutException e) {
timedout = true;
}
}
if(timedout) {
future.cancel(true);
}
}
} catch (InterruptedException | ExecutionException e) {
throw new IllegalStateException("This should never happen");
}
What would be a JUnit based code to run this 3 methods each as 10 concurrent threads.
#RunWith(SpringJUnit4ClassRunner.class
#SpringBootTest
public class TestClass {
#Test
public void readFromDBOneRecord(){
try {
dbService.findOneByID("1");
} catch (Exception error) {
Assert.fail("Unexpected error occured .");
}
}
#Test
public void writeToDBOneRecord(){
try {
dbService.save(entity.builder()
.setID("1").setName("John").build())
} catch (Exception error) {
Assert.fail("Unexpected error occured .");
}
}
#Test
public void deleteDbRecord(){
try {
dbService.delete("1");
} catch (Exception error) {
Assert.fail("Unexpected error occured .");
}
}
}
In some cases some of the methods would throw exceptions. Like if the delete being executed before writeToDBOneRecord.
So the sequence would be say for only 3 threads per method e.g.:
OperationNr|| OperationName || [ThreadNr/total threads per method]OperationType
1. write [2/3]w
2. read [1/3]r
3. read [3/3]r
4. delete [2/3]d
5. read [2/3]r
6. delete [3/3]d ->exception no record
7. write [1/3]w
8. write [3/3]w ->exception record already present
9. delete [1/3]d
What would the code for executing this 3 test methods each in 10 concurrent threads (30 in total)?
As you want to do everything in parallel, I would mix everything and rely on CountDownLatch instances to synchronize the threads as next:
#Test
public void testMultiThreading() throws Exception {
// Total of reader threads
int reader = 5;
// Total of writer threads
int writer = 3;
// Total of remover threads
int remover = 1;
// CountDownLatch used to release all the threads at the same time
final CountDownLatch startSignal = new CountDownLatch(1);
// CountDownLatch used to be notified when all threads did their task
final CountDownLatch doneSignal = new CountDownLatch(reader + writer + remover);
// List in which we collect all the errors
final List<Exception> errors = Collections.synchronizedList(new ArrayList<>());
// Create all the reader threads and start them
for (int i = 0; i < reader; i++) {
Thread thread = new Thread() {
public void run() {
try {
startSignal.await();
dbService.findOneByID("1");
} catch (Exception e) {
errors.add(e);
} finally {
doneSignal.countDown();
}
}
};
thread.start();
}
// Create all the writer threads and start them
for (int i = 0; i < writer; i++) {
Thread thread = new Thread() {
public void run() {
try {
startSignal.await();
dbService.save(entity.builder()
.setID("1").setName("John").build());
} catch (Exception e) {
errors.add(e);
} finally {
doneSignal.countDown();
}
}
};
thread.start();
}
// Create all the remover threads and start them
for (int i = 0; i < remover; i++) {
Thread thread = new Thread() {
public void run() {
try {
startSignal.await();
dbService.delete("1");
} catch (Exception e) {
errors.add(e);
} finally {
doneSignal.countDown();
}
}
};
thread.start();
}
// Release the threads
startSignal.countDown();
// Wait until all threads did their task
doneSignal.await();
// If an error has been collected, print the stack trace and throws the
// first error to make the test fail
if (!errors.isEmpty()) {
for (Exception e : errors) {
e.printStackTrace();
}
throw errors.get(0);
}
}
NB: If you want a given unit test to be executed by several concurrent threads, have a look to contiperf but it won't allow you to mix them as you want to achieve
Guys I'm facing a similar situation
like
This junit case on another thread
though i don't have a junit case. I tried everything that i know of.. including suggestion on that link page, keeping a countdown and thread sleep but the results don't change. if i run through debug and give it some time it shows me all the results from all the thread but if i run it normally it invariably gives me less results.
My code is as belows
`
AtomicInteger atomicInteger = new AtomicInteger(employeeids.size());
CountDownLatch latch = new CountDownLatch(employeeids.size());
Iterable<List<String>> batchList = createBatches(employeeids, batchSize);
Set<Future<List<GradeSearchDTO>>> set = new HashSet<Future<List<GradeSearchDTO>>>();
for(List<String> employeeidsList: batchList) {
Callable<List<GradeSearchDTO>> callable = new ScheduleCallable( employeetype, employeedetails, employeeidsList, dept, seeker, atomicInteger,latch );
Future<List<GradeSearchDTO>> future = pool.submit(callable);
set.add(future);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
latch.await(getTimeOutInMillis(), TimeUnit.MILLISECONDS);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
throw new EmployeeException("Building of Schedules didn't finish in time of ["+getTimeOutInMillis()+"] millis. ");
}
long timeLeft = getTimeOutInMillis();
boolean check=true;
while (check){
logger.debug("Waiting for building asset. countdown value is[" + timeLeft+"]");
try {
Thread.sleep(TIME_TO_PAUSE);
timeLeft = timeLeft - TIME_TO_PAUSE;
if(timeLeft == 0 || timeLeft < 0){
throw new EmployeeException("Building of Schedules didn't finish in time of ["+getTimeOutInMillis()+"] millis. ");
}
for (Future<List<GradeSearchDTO>> future : set) {
if(!future.isDone()){
check=true;
break;
}
else{check=false;}
}
} catch (InterruptedException e) {
logger.error("Error waiting for asset to build to bulid");
}
}
for (Future<List<GradeSearchDTO>> future : set) {
try {
EmployeeScheduleList.addAll(future.get());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static class ScheduleCallable implements Callable
{
private String employeetype;
private List<Employee> employeedetails;
private List<String> employeeidsList;
private String dept;
private EmployeeSeekerHelper seeker;
private AtomicInteger atomicInteger;
private CountDownLatch latch;
public ScheduleCallable(String employeetype,List<Employee> employeedetails,
list<String> employeeidsList, String dept,EmployeeSeekerHelper seeker,AtomicInteger
atomicInteger,CountDownLatch latch )
{
this.employeetype = employeetype;
this.employeedetails = employeedetails;
this.employeeidsList = employeeidsList;
this.dept = dept;
this.seeker = seeker;
this.atomicInteger=atomicInteger;
this.latch=latch;
}
public List<GradeSearchDTO> call()
{
List<GradeSearchDTO> EmployeeScheduleList = new ArrayList<GradeSearchDTO>(0) ;
int counter=1;
for(String scheduleId : employeeidsList)
{
latch.countDown();
EmployeeScheduleList.addAll(searchEmployeeRulesForSchedule(employeetype,employeedetails,scheduleId,dept,seeker,latch));
System.out.println("Thread COUNTER "+counter);
atomicInteger.decrementAndGet();
counter++;
// latch.countDown();
}
return EmployeeScheduleList;
}
}
`
So the above code is perfectly fine... nothing wrong at all. The problem that i faced with the random results was because the method searchEmployeeRulesForSchedule(employeetype,employeedetails,scheduleId,dept,seeker,latch)
which does the business logic under the call() was internally calling a rules engine which was not returning proper results because of the usage of same instance of a class instead of a new instance for each thread.
I refer to this link to create a fixed size threadpool. Then I have a method which allow submit Callable request and get the result, it look like this:
private ExecutorService threadPool = Executors.newFixedThreadPool(5);
private CompletionService<String> pool = new ExecutorCompletionService<String>(threadPool);
public void execute(Callable<String> request){
pool.submit(request);
// what happen if this method is called before get the result???
try {
String result = pool.take().get();
System.out.println("result is " + result);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
This execute method can be called many times and the request has difference execute time. The problem is that I want to get the result immediately when it finished. And I want to make sure when executing this method, other calls can be handled and allow add to thread poll.
Here is an example usage:
final Random rnd = new Random();
for (int i = 0; i < 5; i++) {
final String value = String.valueOf(i);
execute(new Callable<String>() {
#Override
public String call() throws Exception {
int sleep = rnd.nextInt(10) * 100;
System.out.println("sleep in " + sleep);
Thread.sleep(sleep);
return value;
}
});
}
And the results are always in order although they have difference execute time:
sleep in 900
result is 0
sleep in 300
result is 1
sleep in 0
result is 2
sleep in 500
result is 3
sleep in 600
result is 4
And I also used the future, but it doesn't work too.
private static void execute(Callable<String> request){
Future<String> future = threadPool.submit(request);
try {
String result = future.get();
System.out.println("result is " + result);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
Please tell me how can I do that? Thanks in advance.
You aren't using the CompletionService correctly. Your main thread is producing tasks and consuming results. A CompletionService is intended to decouple production and consumption; you'd use it when you have different threads playing these roles. The execute() method makes no sense; it is effectively doing this, but with a lot of obfuscation and overhead:
public void execute(Callable<String> request) {
try {
System.out.println("result is " + request.call());
} catch (Exception ex) {
ex.printStackTrace();
}
}
If you must consume the result as soon as it's ready, you have to make that part of the task. Otherwise, you need one application thread waiting for every task to complete, because if you don't, a task result might be ready and have to wait for a thread to be available to consume it. And if you have one thread per task already, why use a thread pool?
To be more explicit, if you want to guarantee no waiting, you need to do something like this:
final class MyTask implements Callable<Void> {
private final String value;
MyTask(String value) { this.value = value; }
#Override
public Void call() throws InterruptedException {
String result = doWork();
handleResult(result);
return null;
}
private String doWork() throws InterruptedException {
int sleep = ThreadLocalRandom.current().nextInt(10) * 100;
System.out.println("sleep in " + sleep);
Thread.sleep(sleep);
return value;
}
private void handleResult(String result) {
System.out.println("result is " + result);
}
}
If you want to use a CompletionService, you need some separate threads that take() from the service. But in this approach, if tasks are completed faster than they are consumed, some results will wait.
R4j,
the get() waits for the callable to return with the value from call: if you want to submit 5 requests you need to submit all requests and then call get