Java: Controlling hardware tasks with pausable ThreadPoolExecutor - java

I want to implement a single-producer - multi-consumer logic where each consumer processing time depends on a hardware response.
**EDIT
I have a Set of objects (devices). Each object (device) corresponds to a hardware real unit I want to simulate in software.
My main class distributes a list of tasks to each device. Each task takes a certain time to complete - which I want to have control, in order to simulate the hardware operation. Each device object has its own SingleThreadExecutorService service executor to manage its own queued tasks. A Sleep on a task of a specific device object should not interfere on main, or other devices object's performance.
So far things are working but I am not sure how to get a future from the tasks without blocking the main thread with a while(!future.isDone()). When I do it, two problems occur:
task 1 is submitted to device[ 1 ].executor. Tasks 1 sleeps to simulate hardware operation time.
task 2 should be submitted to device[ 2 ].executor as soon as task 1 is submitted, but it won't, because main thread is hold while waiting for task 1 to return a Future. This issue accumulates delay on the simulation since every task added causes the next device to have to wait for the previous to complete, instead of running simultaneously.
Orange line indicates a command to force device to wait for 1000 milliseconds.
When Future returns, it then submits a new task to device 2, but it is already 1 second late, seen in blue line. And so on, green line shows the delay increment.
If I don't use Future to get when tasks were finished, the simulation seems to run correctly. I couldn't find a way to use future.isDone() without having to create a new thread just to check it. Also, I would really be glad if someone could advice me how to proceed in this scenario.

If your goal is to implement something where each consumer task is talking to a hardware device during the processing of its task, then the run method of the task should simply talk to the device and block until it receives the response from the device. (How you do that will depend on the device and its API ...)
If your goal is to do the above with a simulated device (i.e. for testing purposes) then have the task call Thread.sleep(...) to simulate the time that the device would take to respond.
Based on your problem description (as I understand it), the PausableSchedulerThreadPoolExecutor class that you have found won't help. What that class does is to pause the threads themselves. All of them.
UPDATE
task 2 should be submitted to device[ 2 ].executor as soon as task 1 is submitted, but it won't, because main thread is hold while waiting for task 1 to return a Future.
That is not correct. The Future object is returned immediately ... when the task is submitted.
You mistake (probably) is that the main thread is calling get on the Future. That will block. But the point is that is your main thread actually needs to call get on the Future before submitting the next task then it is essentially single-threaded.
Real solution: figure out how to break that dependency that makes your application single threaded. (But beware: if you pass the Future as a parameter to a task, then the corresponding worker thread may block. Unless you have enough threads in the thread pool you could end up with starvation and reduced concurrency.)

Related

run things in parallel with multithreading [duplicate]

In my Java application I have a Runnable such as:
this.runner = new Runnable({
#Override
public void run() {
// do something that takes roughly 5 seconds.
}
});
I need to run this roughly every 30 seconds (although this can vary) in a separate thread. The nature of the code is such that I can run it and forget about it (whether it succeeds or fails). I do this as follows as a single line of code in my application:
(new Thread(this.runner)).start()
Now, this works fine. However, I'm wondering if there is any sort of cleanup I should be doing on each of the thread instances after they finish running? I am doing CPU profiling of this application in VisualVM and I can see that, over the course of 1 hour runtime, a lot of threads are being created. Is this concern valid or is everything OK?
N.B. The reason I start a new Thread instead of simply defining this.runner as a Thread, is that I sometimes need to run this.runner twice simultaneously (before the first run call has finished), and I can't do that if I defined this.runner as a Thread since a single Thread object can only be run again once the initial execution has finished.
Java objects that need to be "cleaned up" or "closed" after use conventionally implement the AutoCloseable interface. This makes it easy to do the clean up using try-with-resources. The Thread class does not implement AutoCloseable, and has no "close" or "dispose" method. So, you do not need to do any explicit clean up.
However
(new Thread(this.runner)).start()
is not guaranteed to immediately start computation of the Runnable. You might not care whether it succeeds or fails, but I guess you do care whether it runs at all. And you might want to limit the number of these tasks running concurrently. You might want only one to run at once, for example. So you might want to join() the thread (or, perhaps, join with a timeout). Joining the thread will ensure that the thread will completes its computation. Joining the thread with a timeout increases the chance that the thread starts its computation (because the current thread will be suspended, freeing a CPU that might run the other thread).
However, creating multiple threads to perform regular or frequent tasks is not recommended. You should instead submit tasks to a thread pool. That will enable you to control the maximum amount of concurrency, and can provide you with other benefits (such as prioritising different tasks), and amortises the expense of creating threads.
You can configure a thread pool to use a fixed length (bounded) task queue and to cause submitting threads to execute submitted tasks itself themselves when the queue is full. By doing that you can guarantee that tasks submitted to the thread pool are (eventually) executed. The documentation of ThreadPool.execute(Runnable) says it
Executes the given task sometime in the future
which suggests that the implementation guarantees that it will eventually run all submitted tasks even if you do not do those specific tasks to ensure submitted tasks are executed.
I recommend you to look at the Concurrency API. There are numerous pre-defined methods for general use. By using ExecutorService you can call the shutdown method after submitting tasks to the executor which stops accepting new tasks, waits for previously submitted tasks to execute, and then terminates the executor.
For a short introduction:
https://www.baeldung.com/java-executor-service-tutorial

Do I need to clean up Thread objects in Java?

In my Java application I have a Runnable such as:
this.runner = new Runnable({
#Override
public void run() {
// do something that takes roughly 5 seconds.
}
});
I need to run this roughly every 30 seconds (although this can vary) in a separate thread. The nature of the code is such that I can run it and forget about it (whether it succeeds or fails). I do this as follows as a single line of code in my application:
(new Thread(this.runner)).start()
Now, this works fine. However, I'm wondering if there is any sort of cleanup I should be doing on each of the thread instances after they finish running? I am doing CPU profiling of this application in VisualVM and I can see that, over the course of 1 hour runtime, a lot of threads are being created. Is this concern valid or is everything OK?
N.B. The reason I start a new Thread instead of simply defining this.runner as a Thread, is that I sometimes need to run this.runner twice simultaneously (before the first run call has finished), and I can't do that if I defined this.runner as a Thread since a single Thread object can only be run again once the initial execution has finished.
Java objects that need to be "cleaned up" or "closed" after use conventionally implement the AutoCloseable interface. This makes it easy to do the clean up using try-with-resources. The Thread class does not implement AutoCloseable, and has no "close" or "dispose" method. So, you do not need to do any explicit clean up.
However
(new Thread(this.runner)).start()
is not guaranteed to immediately start computation of the Runnable. You might not care whether it succeeds or fails, but I guess you do care whether it runs at all. And you might want to limit the number of these tasks running concurrently. You might want only one to run at once, for example. So you might want to join() the thread (or, perhaps, join with a timeout). Joining the thread will ensure that the thread will completes its computation. Joining the thread with a timeout increases the chance that the thread starts its computation (because the current thread will be suspended, freeing a CPU that might run the other thread).
However, creating multiple threads to perform regular or frequent tasks is not recommended. You should instead submit tasks to a thread pool. That will enable you to control the maximum amount of concurrency, and can provide you with other benefits (such as prioritising different tasks), and amortises the expense of creating threads.
You can configure a thread pool to use a fixed length (bounded) task queue and to cause submitting threads to execute submitted tasks itself themselves when the queue is full. By doing that you can guarantee that tasks submitted to the thread pool are (eventually) executed. The documentation of ThreadPool.execute(Runnable) says it
Executes the given task sometime in the future
which suggests that the implementation guarantees that it will eventually run all submitted tasks even if you do not do those specific tasks to ensure submitted tasks are executed.
I recommend you to look at the Concurrency API. There are numerous pre-defined methods for general use. By using ExecutorService you can call the shutdown method after submitting tasks to the executor which stops accepting new tasks, waits for previously submitted tasks to execute, and then terminates the executor.
For a short introduction:
https://www.baeldung.com/java-executor-service-tutorial

Long running HTTP request and threads synchronization

I need to code a web service that solves a complex problem by the use of a heuristic algorithm. The algorithm will run as long as the amount of time specified in the POST request has lapsed (i.e. passing timeAllowance=60 will make sure that the heuristic algorithm stops after 60 seconds and returns the best solution found).
The heuristic algorithm has to run on several threads to take advantage of all the server cores. During the execution of the algorithm, these methods have to "communicate" between each other. Each thread will run the heuristic algorithm and after certain amount of time, the threads will communicate the solutions they found and, if the allowed time has not expired, a new cycle is run with a different initial population. Summarizing:
Generate initial populations (pretty much randomly)
Launch heuristic algorithms threads, each one taking a population as input
After a certain amount of time, terminate the threads and communicate to a "controller entity" the new populations found by the threads
Do some logical reasoning and generate the new populations based on the result of the threads launched at point 2
If the allowed time has not expired, go back to point 2 with the new populations. Otherwise quit
My question is: how would you structure the code using Spring MVC?
Just as a test, I tried to launch 10 threads in a service method and to call that method from a controller (autowiring the service). Everything the threads are doing is to sleep for 60 seconds. I was expecting the HTTP request to wait for all the threads to terminate (i.e. about 60 seconds), but it actually responds straight away.
Any help very much appreciated.
Thank you!
You don't want thread, you want a thread pool (ExecutorService). Submit some number of Callable<HeuristicResult> to your pool and wait on returned Future<HeuristicResult>. Once all futures are done, do your point 4. and go back to 2. (but reusing the thread pool).
At the end shutdown the pool or reuse it for all requests (more scalable).
I tried to launch 10 threads [...] I was expecting the HTTP request to wait for all the threads to terminate [...], but it actually responds straight away.
Starting a thread is non-blocking and from that moment thread works asynchronously. You can call join() on created thread to wait for its termination. But a thread pool and Future.get() is much more modern and flexible.
Without seeing any code I would guess that reason this returned straight away is that you started the task in a background thread not the thread servicing the request.
If I were writing this service I would probably not wait for 60 seconds before returning the response. I would start the task in the background (using a service) and return a status page immediately. On this page you could use ajax to poll the server for the status of the task and use javascript to render a progress bar in the browser.
Therefore you would need a controller method to start the process and one to allow the browser to obtain the status. Since you just need the time since it started to derive the progress I would most likely just put the start time and total allowed time in the session. Then you need a controller method to calculate the percentage of time elapsed and return that to the browser.

Help with a task scheduling algorithm

I am working on an application in which thousands of tasks associated
with hundreds of devices, each task requiring, < 5ms to begin execution, and
taking on average 100ms to complete.
The conditions are as such:
Each device can only process a single
task at a time, e.g., one task must finish running on its assigned
device prior to subsequent task's being processeed.
The scheduler should be efficient. Currently, processing a given device's
work queue takes longer than the sum of it's tasks.
Here is basic description of the current implementation:
Each device contains a work queue which is filled with tasks associated with
that device.
When a task is enqueued, that device's work queue is placed into a
global run queue (a queue of queue's). The global run queue is consumed by a worker thread
which dequeue's the device's task objects, processes one, then places
the device queue at the back of the global run queue. When that given device
has been dequeued again, the worker thread checks to see if the task has completed,
if so, the next task is executed. This process continues, until all device queues
have been depleted of tasks in the global runqueue.
Any suggestions for improvements? Have I stated this clearly? If not, please let me know, and I'll do my best to clarify.
Thanks for taking the time to look this over. Regards.
How about something like the ExecutorCompletionService together with a ThreadPoolExecutor. This gives you callback on completion, which you can use to submit subsequent jobs, and a managed threadpool of executors, which you can tweak to improve throughput.
I suggest you run your code through a profiler to see which threads are currently blocking (sounds like it will be your producer device threads). I can recommend YourKit Java Profiler, however its not free.
The problem with your design is that only one task is run at a time, which means that any device is idle while any other device is in use.
Since there are hundreds of devices, it would probably not be a good idea to assign a thread to each of these devices, but a thread pool could very well be used.

handling sleep in java scheduled executor service

I have a sort of complex problem like below.
- we have a real time system with large number threads requirement. In order to optimize the performance, we are thinking of following design.
create a thread pool executor with max number of threads
each thread is used to create scheduled executor service.
now the tasks are being assigned to these executor services evenly based on load
BUT the biggest problem is, if one of the task in the queue contains a sleep (for few secs), it blocks the corresponding Schedule executor service thread for that duration and subsequently all the following tasks in that queue.
In this regard, please suggest me how to suspend the execution of the task with sleep OR overriding the sleep somehow and rejoin/schedule the task again to the queue.
Thanks in advance
Seshu
Assuming I understand your question, your Schedule Executor service threads have a deadline requirement, but the actual workers can sleep for an unknown length of time, possibly throwing off the timing of the Schedule Executors. From your description I'm guessing what you want is for a task that needs to sleep to actually stop, save progress information and then requeue itself for the remainder of the work to be rescheduled at some future time. You'd have to build this into your application architecture.
Alternatively, you could have the scheduler threads launch the worker tasks in their own separate threads, letting them sleep as necessary, with one scheduler thread collecting all the worker terminations.
To get a better answer you're going to have to provide more information about what you're trying to accomplish.
Tasks which sleep are inherently unfriendly for running in any kind of bounded thread pool. The sleep is explicitly telling the thread that it must do nothing for a period of time.
If possible, split the task into 2 (or more parts), eliminating the sleep completely. Get the first half-task to schedule the second task with an appropriate delay.
Failing that, you could consider increasing the size of your thread pool somewhat - either setting a much larger cap to its size, or possibly even eliminating the cap altogether (not recommended for a server than might end up with many clients).
Alternatively, move the tasks with sleep statements in them into their own Scheduled executor. Then, they'll delay each other, but better-behaved tasks, with no wait statements in them, will get preferential treatment.

Categories