ThreadPoolExecutor Utility methods - java

I am writing a thread pool utility in my multithreading program. i just need to validate the following methods are correct and are they return the right values for me. i am using a LinkedBlockingQueue with size of 1. and also I refer to the java doc and it always says 'method will return approximate' number phrase. so i doubt weather following conditions are correct.
public boolean isPoolIdle() {
return myThreadPool.getActiveCount() == 0;
}
public int getAcceptableTaskCount() {
//initially poolSize is 0 ( after pool executes something it started to change )
if (myThreadPool.getPoolSize() == 0) {
return myThreadPool.getCorePoolSize() - myThreadPool.getActiveCount();
}
return myThreadPool.getPoolSize() - myThreadPool.getActiveCount();
}
public boolean isPoolReadyToAcceptTasks(){
return myThreadPool.getActiveCount()<myThreadPool.getCorePoolSize();
}
Please let me know your thoughts and suggestions.
UPDATE
interesting thing was if pool returns me there are 3 threads available from the getAcceptableTaskCount method and when i pass 3 tasks to the pool some times one task got rejected and it is handle by RejectedExecutionHandler. some times pool will handle all the tasks i passed. i am wondering why pool is rejected the tasks since i am passing tasks according to the available thread count.
--------- implementation of the answer of gray---
class MyTask implements Runnable {
#Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("exec");
}
}
#Test
public void testTPool(){
ExecutorService pool = Executors.newFixedThreadPool(5);
List<Future<MyTask>> list = new ArrayList<Future<MyTask>>();
for (int i = 0; i < 5; i++) {
MyTask t = new MyTask();
list.add(pool.submit(t, t));
}
for (int i = 0; i < list.size(); i++) {
Future<MyTask> t = list.get(i);
System.out.println("Result -"+t.isDone());
MyTask m = new MyTask();
list.add(pool.submit(m,m));
}
}
This will print Result -false in the console meaning that task is not complete.

From your comments:
i need to know that if pool is idle or pool can accept the tasks. if pool can accept, i need to know how much free threads in the pool. if it is 5 i will send 5 tasks to the pool to do the processing.
I don't think that you should be doing the pool accounting yourself. For your thread pool if you use Executors.newFixedThreadPool(5) then you can submit as many tasks as you want and it will only run them in 5 threads.
so i get the first most 5 tasks from the vector and assign them to the pool.ignore the other tasks in the vector since they may be update / remove from a separate cycle
Ok, I see. So you want to maximize parallelization while at the same time not pre-loading jobs? I would think that something like the following pseudo code would work:
int numThreads = 5;
ExecutorService threadPool = Executors.newFixedThreadPool(numThreads);
List<Future<MyJob>> futures = new ArrayList<Future<MyJob>>();
// submit the initial jobs
for (int i = 0; i < numThreads; i++) {
MyJob myJob = getNextBestJob();
futures.add(threadPool.submit(myJob, myJob));
}
// the list is growing so we use for i
for (int i = 0; i < futures.size(); i++) {
// wait for a job to finish
MyJob myJob = futures.get(i);
// process the job somehow
// get the next best job now that the previous one finished
MyJob nextJob = getNextBestJob();
if (nextJob != null) {
// submit the next job unless we are done
futures.add(threadPool.submit(myJob, myJob));
}
}
However, I don't quite understand how the thread count would change however. If you edit your question with some more details I can tweak my response.

Related

Why Set.add() method does not work in anonymous Runnable?

I would like to run 20 threads simultaneously to test my id generator. However, uniqueSet.add(id) is not adding id to the set. When I assert, it says set size is zero.
#Test
void should_generate_unique_id_concurrently() throws InterruptedException {
Set<Long> uniqueSet = ConcurrentHashMap.newKeySet();
final int numberOfThreads = 20;
ExecutorService service = Executors.newFixedThreadPool(numberOfThreads);
CountDownLatch latch = new CountDownLatch(numberOfThreads);
for (int i = 0; i < numberOfThreads; i++) {
service.submit(() -> {
try {
latch.countDown();
latch.await();
long id = idGenerator.nextId();
uniqueSet.add(id);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
assertEquals(numberOfThreads, uniqueSet.size());
}
The uniqueSet.add(id) probably is working just fine. But most likely, none of those tasks is able to execute that line before the main thread asks for the size of the set.
Each of your task calls latch.countDown() before it does anything else. That means, none of the tasks will be able to do anything else until all twenty of them have been started.
Meanwhile, your main thread asks for the size of the set immediately after it submits the last task to the thread pool. The main thread already is running at that point. Probably most of the pool threads are sleeping in latch.await() The ones that aren't haven't even got that far yet. The main thread probably always calls uniqueSet.size() before any of the worker threads reaches the uniqueSet.add(id) line.
#VGR suggested a good solution to your problem: After your main thread has submitted the twenty tasks, and before it checks the size of the set, it could shut the thread pool down:
for (int i = 0; i < numberOfThreads; i++) {
service.submit(...);
}
// Tell the `service` to refuse new tasks, and to shut down
// _after_ all of the pending tasks have completed.
service.shutdown();
// Wait until all of the tasks have completed.
service.awaitTermination();
assertEquals(numberOfThreads, uniqueSet.size());

Is there a better way to use a CountUpDownLatch than Await?

I'm using a count up/down latch to keep a program limited to 6 threads, it works but what I really want is to always have 6 threads running. So that when one thread dies, another one starts up. With the implementation below, it only creates 6 new threads at a time, whenever the timeout expires.
Any suggestions on how to struct my loop to accomplish this?
int numThreads = 6;
CountUpDownLatch threadCounter = new CountUpDownLatch();
for(int t = 1; t <= numThreads; t++) {
while(list.hasNext()) {
new Thread(new ThreadController("processData",list.next())).start();
threadCounter.countUp();
}
try {
threadCounter.await(5, TimeUnit.MINUTES);
} catch (InterruptedException e) { e.printStackTrace(); }
}
Use an executor service which contains 6 threads like so,
ExecutorService exec = Executors.newFixedThreadPool(6);
for (int i = 0; i < 10; i++) {
exec.submit(() -> System.out.println("Hello"));
}
exec.shutdown();
You can either pass a Runnable or a Callable to the submit method of the ExecutorService. Here I have passed a lambda function as a Runnable which is valid starting from Java8. In your case you may do it like so,
exec.submit(new ThreadController("processData",list.next()));

main thread consumer and other threads producer

My questions is, I have a data set of 1000 records. I want 3 threads that process the data like this,
thread1 from record 1 to 300, thread2 from 301 to 600 and so on. One thread can make a request and fetch 50 records at a time, create an object and put it in a queue.
Main thread will simultaneously read data from the queue.
Below is the code, the problem I am facing is that recordRead variable tells the starting point from where the thread should start reading the records.
But how can I set different value for each thread e.g for thread1 it should be 0 and recordsToRead should be 300 and for thread2, recordRead should be 300 and recordsToRead to be 300+300=600 and for last thread it should be 600 and upto the end.
pagesize=50
pagesize,recordRead and recordToRead are all variables that belong to main class and main thread.
ExecutorService service = Executors.newFixedThreadPool(nThreads);
while(nThreads > 0) {
nThreads--;
service.execute(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
do {
int respCode = 0;
int RecordsToRead = div;
JSONObject jsObj = new JSONObject();
jsObj.put("pagesize", pageSize);
jsObj.put("start", recordsRead);
jsObj.put("searchinternalid", searchInternalId);
try {
boolean status = req.invoke(jsObj);
respCode = req.getResponseCode();
} catch (Exception e) {
req.reset();
e.printStackTrace();
return true;
}
JSONObject jsResp = req.getResponseJson();
//here jsResp will be added to ArrayBlockingQueue.
req.reset();
}while(!isError && !isMaxLimit && recordsRead < RecordsToRead);
}
});
}
After this loop will be the code of main thread reading the queue.
how can I set recordsRead and recordToread for all threads.
And how to make main thread wait untill atleast one thread inserts an object in queue.
I see in you definition two problems. First problem is to perform parallel chunk computation and second one is to create a continous pipeline from this. Lets start from the first problem. To make parallel computations with predefined size the best option fmpv will be to use fork-join framework. Not only by performance (work stealing is really effective) but also due to simpler code. But since you are limited to 3 threads for me it also seems valid to use threads directly. Simply what you want can me implemented by this way:
final int chunkSize = 300;
//you can also use total amount of job
//int totalWork = 1000 and chunk size equals totalWork/threadsNumber
final int threadsNumber = 3;
Thread[] threads = new Thread[threadsNumber];
for (int ii = 0; ii < threadsNumber; ii++) {
final int i = ii;
threads[ii] = new Thread(() -> {
//count your variable according the volume
// for example you can do so
int chunkStart = i * chunkSize;
int chunkEnd = chunkStart + chunkSize;
for(int j = chunkStart; j < chunkEnd; j++) {
//object creation with necessary proprs
//offer to queue here
}
});
threads[ii].start();
}
//your code here
//take here
for (int ii = 0; ii < threadsNumber; ii++) {
try {
//this part is only as example
//you do not need it
//here if you want you can also w8 for completion of all threads
threads[ii].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Now about the second problem with consuming. For this puprose you can use for example ConcurrentLinkedBlockingQueue (http://www.jgroups.org/javadoc/org/jgroups/util/ConcurrentLinkedBlockingQueue.html). Make offer in producer threads and use take method in main.
But to be honest i still did not get the reason of your problem. Do you want to create continuous pipeline or it is just one-time computation?
Also i will recommend you to take this course: https://www.coursera.org/learn/parallel-programming-in-java/home/welcome.
This will help you exactly with your problem and provide various solutions. There are also concurrent and distributed computing courses.

In Java, how to pass the objects back to Main thread from worker threads?

In Java, how to pass the objects back to Main thread from worker threads? Take the following codes as an example:
main(String[] args) {
String[] inputs;
Result[] results;
Thread[] workers = new WorkerThread[numThreads];
for (int i = 0; i < numThreads; i++) {
workers[i] = new WorkerThread(i, inputs[i], results[i]);
workers[i].start();
}
....
}
....
class WorkerThread extends Thread {
String input;
int name;
Result result;
WorkerThread(int name, String input, Result result) {
super(name+"");
this.name = name;
this.input = input;
this.result = result;
}
public void run() {
result = Processor.process(input);
}
}
How to pass the result back to main's results[i] ?
How about passing this to WorkerThread,
workers[i] = new WorkerThread(i, inputs[i], results[i], this);
so that it could
mainThread.reults[i] = Processor.process(inputs[i]);
Why don't you use Callables and an ExecutorService?
main(String[] args) {
String[] inputs;
Future<Result>[] results;
for (int i = 0; i < inputs.length; i++) {
results[i] = executor.submit(new Worker(inputs[i]);
}
for (int i = 0; i < inputs.length; i++) {
Result r = results[i].get();
// do something with the result
}
}
#Thilo's and #Erickson's answers are the best one. There are existing APIs that do this kind of thing simply and reliably.
But if you want to persist with your current approach of doing it by hand, then the following change to you code may be sufficient:
for (int i = 0; i < numThreads; i++) {
results[i] = new Result();
...
workers[i] = new WorkerThread(i, inputs[i], results[i]);
workers[i].start();
}
...
public void run() {
Result tmp = Processor.process(input);
this.result.updateFrom(tmp);
// ... where the updateFrom method copies the state of tmp into
// the Result object that was passed from the main thread.
}
Another approach is to replace Result[] in the main program with Result[][] and pass a Result[0] to the child thread that can be updated with the result object. (A light-weight holder).
However, there us an Important Gotcha when you are implementing this at a low level is that the main thread needs to call Thread.join on all of the child threads before attempting to retrieve the results. If you don't, there is a risk that the main thread will occasionally see stale values in the Result objects. The join also ensures that the main thread doesn't try to access a Result before the corresponding child thread has completed it.
The main thread will need to wait for the worker threads to complete before getting the results. One way to do this is for the main thread to wait for each worker thread to terminate before attempting to read the result. A thread terminates when its run() method completes.
For example:
for (int i = 0; i < workers.length; i++) {
worker.join(); // wait for worker thread to terminate
Result result = results[i]; // get the worker thread's result
// process the result here...
}
You still have to arrange for the worker thread's result to be inserted into the result[] array somehow. As one possibility, you could do this by passing the array and an index into each worker thread and having the worker thread assign the result before terminating.
Some typical solutions would be:
Hold the result in the worker thread's instance (be it Runnable or Thread). This is similar to the use of the Future interface.
Use a BlockingQueue that the worker threads are constructed with which they can place their result into.
Simple use the ExecutorService and Callable interfaces to get a Future which can be asked for the result.
It looks like your goal is to perform the computation in parallel, then once all results are available to the main thread, it can continue and use them.
If that's the case, implement your parallel computation as a Callable rather than a thread. Pass this collection of tasks to the invokeAll() method of an ExecutorService. This method will block until all the tasks have been completed, and then your main thread can continue.
I think I have a better solution, why don't you make your worker threads pass the result into a linkedListBlockingQueue, which is passed to them, after they are done, and your main function picks the results up from the queue like this
while(true){linkedListBlockingQueue.take();
//todo: fil in the task you want it to do
//if a specific kind of object is returned/countdownlatch is finished exit
}

I am confused about Java multithread

I am developing a program that can send http requests to fetch documents.
I have fill a queue with all the requests items:
Queue<RequestItem> requestItems = buildRequest4Docs();
Then,
int threadNum = requestItems.size();
//ExecutorService exs = Executors.newFixedThreadPool(threadNum);
for (int i = 0; i < threadNum; i++) {
ResponseInterface response = new CMSGOResponse();
RequestTask task = new RequestTask(requestItems.poll(), this, response);
task.run();
//exs.execute(new RequestTask(requestItems.poll(), this, response));
}
//exs.shutdown();
I am confused here, in the for loop,does the tasks run simultaneously? Or the tasks run one by one?
Thanks!
In the way you got it now the tasks will be executed one by one. If you uncomment the code you got now as comments and comment the lines RequestTask task = new RequestTask(requestItems.poll(), this, response); and task.run(); you will get a concurrent execution.
So for the concurrent execution it has to look like this:
int threadNum = requestItems.size();
ExecutorService exs = Executors.newFixedThreadPool(threadNum);
for (int i = 0; i < threadNum; i++) {
ResponseInterface response = new CMSGOResponse();
exs.execute(new RequestTask(requestItems.poll(), this, response));
}
exs.shutdown();
while (! exs.isTerminated()) {
try {
exs.awaitTermination(1L, TimeUnit.DAYS);
}
catch (InterruptedException e) {
// you may or may not care here, but if you truly want to
// wait for the pool to shutdown, just ignore the exception
// otherwise you'll have to deal with the exception and
// make a decision to drop out of the loop or something else.
}
}
In addition to that I suggest, that you do not bind the amount of threads created with the ExecutorService to the amount of task you got to work. Connecting it to the amount of processors of the host system is usually a better method. To get the amount of processors use: Runtime.getRuntime().availableProcessors()
And in the executor service initialized like this you put the items of your queue. But that works nicely without fetching the total size, rather by polling the Queue until it does not return additional data.
The final result of my proposals could look like this:
final int threadNum = Runtime.getRuntime().availableProcessors();
final ExecutorService exs = Executors.newFixedThreadPool(threadNum);
while (true) {
final RequestItem requestItem = requestItems.poll();
if (requestItem == null) {
break;
}
final ResponseInterface response = new CMSGOResponse();
exs.execute(new RequestTask(requestItem , this, response));
}
exs.shutdown();
I am confused here, in the for loop,does the tasks run simultaneously? Or the tasks run one by one?
With the code you've posted, they'll run one-by-one, because (assuming RequestTask is a subclass of Thread) you've called run. You should call start. Now that you've said RequestTask implements Runnable, the correct code wouldn't call start (it doesn't have one!) but rather new Thread(task);. (But it looks like you've now received a good answer regarding the ExecutorService, which is another way to do it.)
Assuming you call start start them on different threads instead, then yes, they'll all run in parallel (as much as they can on the hardware, etc.).
Currently you are running your thread sequentially, Well you have two ways to run threads.(Assuming that RequestTask extends Thread)
I.Either create thread object and call start() method.
RequestTask task = new RequestTask(requestItems.poll(), this, response);
task.start(); // run() method will be called, you don't need to call it
II.Or create ExecutorService
ExecutorService pool = Executors.newFixedThreadPool(poolSize);
//....
for (int i = 0; i < threadNum; i++) {
ResponseInterface response = new CMSGOResponse();
RequestTask task = new RequestTask(requestItems.poll(), this, response);
pool.execute(task);
}
You are running them one by one in the current thread. You need to use the ExecutorService to run them concurrently.
I am confused here, in the for loop,does the tasks run simultaneously? Or the tasks run one by one?
Task will be executed in the same thread i.e. one by one since you are calling run() rather that start , it will not run the task in new thread .
int threadNum = requestItems.size();
ExecutorService exs = Executors.newFixedThreadPool(threadNum);
ResponseInterface response = new CMSGOResponse();
RequestTask task = new RequestTask(requestItems.poll(), this, response);
exs.execute(task );
exs.shutdown();
In above case task will be executed in new thread and as soon as you assign 10 different task to ExecutorService they will be executed asynchronously in different threads.
I usually tend to create my Threads (or classes implementing Interface), THEN launch them with the start() method.
In your case, since RequestTask implements Runnable, you could add a start() method like this :
public class RequestTask implements Runnable {
Thread t;
boolean running;
public RequestTask() {
t = new Thread(this);
}
public void start() {
running = true; // you could use a setter
t.start();
}
public void run() {
while (running) {
// your code goes here
}
}
}
, then :
int threadNum = requestItems.size();
RequestTask[] rta = new RequestTask[threadNum];
// Create the so-called Threads ...
for (int i=0;i<threadNum;i++) {
rta[i] = new RequestTask(requestItems.poll(), this, new CMSGOResponse());
}
// ... THEN launch them
for (int i=0;i<threadNum;i++) {
rta[i].start();
}

Categories