Pardon my ignorance if this is a basic question.
I want to understand how can I return control from a module and start processing in background?
Lets start component A calls component B. Component B does some basic processing, starts a background thread and immediately returns control to A. Whenever background thread completes its processing it is going to store the result in a persistence store. Whole processing by this background thread is time consuming and A cannot wait until background thread finishes off.
Component A {
Http Call component B
}
Component B {
// Got request from component A
start background thread();
return; // don't wait till background thread finishes off
}
background thread() {
// time consuming task
}
How can I achieve this behavior in java? I don't think it is entirely asynchronous form of processing since communication is happening over http connection that has timeout settings.
Update:
Component A:
Receives Http call
Component B:
Approach1:
Runnable runnable = new MyThread();
new Thread(runnable).start();
Approach2:
ExecutorService exec = Executors.newSingleThreadExecutor();
exec.execute(new MyThread());
exec.shutdown();
Both of the above mentioned approaches helped me to start background processing and return immediate control to A.
Use threads at a raw level is good solution for some easy proof of concepts, but I strongly suggest at least try to use the concurrent API from java, you can find the documentation here. and a good tutorial is here
The simplest approach is to create a Callable object that contains the instruction you want to execute in background.
Callable myInstructions = new Callable<ObjectToReturn>() {
public ObjectToReturncall() {
return object.methodCall();
}}
Using the ExecutorService submit this callable to expect a Future object.
Future<ObjectToReturn> future = executor.submit(myInstructions);
//Do anything else as this wont be blocked ..
Future API have a set of method to ask if the task is already completed.
if(future.isDone()) // Ask if the task is done
ObjectToReturn solution = future.get() // Get the result
Very simple to use the Future API .
EDIT
If you dont expect any response from the Future api, just do an operation you could use
Future<Void> future = executor.submit(new Callable<Void>() {
public Void call() throws Exception {
testA.abc();
return null;
}
});
Other option if you dont want to receive a result or get a response, just fire a thread will be
ExecutorService executor = Executors.newFixedThreadPool(5);`
executor.execute(new RunnableClass());
Also avoid call shutdown on ExecutorService , do that just until the end of the process, when you dont have more time to do, in spring or container fwks the container is in charge of shutdown the ExecutorService once the app has been shutdown
The easiest way would probably be to create a new java Thread with the background processing logic as parameter.
void componentB() {
new Thread(new Runnable() {
#Override
public void run() {
// Time consuming task.
}
}).start();
// The method continues without stopping.
}
In later versions of java, you can also use the ForkJoinPool-class to achieve this:
public class Main {
private final ExecutorService executor = new ForkJoinPool();
void componentA() {
componentB();
}
void componentB() {
executor.execute(this::timeConsumingTask);
// The method continues without stopping.
}
private void timeConsumingTask() {
// Time consuming task.
}
}
Assuming you want the HTTP call to return before the background processing is complete, your pseudocode is perfectly valid for Java.
At the next level of detail, check out the Javadoc for Thread, Runnable, and the java.nio library classes.
Related
I have a JSP application in which a webpage calls five methods one by one (all of them fetch data from different sources) and display charts based on data.
To load the webpage fastly, I planned to call all the five methods in parallel with the help of FixedThreadPool Executor.
Should I shut down my executor once I get the result from all five methods? Shutting down the executor is a bad idea according to me, since if someone opens the webpage a second time it will require the executor to initialize again in order to call the five methods parallelly.
However, I'm not sure about the consequences of leaving the executor open so not sure how to proceed.
Leaving it open is the normal way to use a thread pool. That's the whole point of thread pools: It's to prevent your application from having to create and then destroy however many new threads every time it needs to load a page. Instead, it can just use the same threads again and again.
In chapter 7 of "Java Concurrency in Practice" there is an example just like this, where a so called one-shot execution service is proposed:
If a method needs to process a batch of tasks and does not return until all the
tasks are finished, it can simplify service lifecycle management by using a private
Executor whose lifetime is bounded by that method.
Its code example:
boolean checkMail(Set<String> hosts, long timeout, TimeUnit unit)
throws InterruptedException {
ExecutorService exec = Executors.newCachedThreadPool();
final AtomicBoolean hasNewMail = new AtomicBoolean(false);
try {
for (final String host : hosts)
exec.execute(new Runnable() {
public void run() {
if (checkMail(host))
hasNewMail.set(true);
}
});
} finally {
exec.shutdown();
exec.awaitTermination(timeout, unit);
}
return hasNewMail.get();
}
I'd suggest simplifying your code using this approach.
We have a glue component between legacy code and current code. Essentially the whole legacy application is single threaded and has horrible issues where a ui refresh for a single instruction can happen 5 to 8 times.
I want to publish an async message after the first update request happens +2 seconds.
Let's not get stuck on the why, this is not what I want to really do, but I have to understand how to at least do this so I can implement a real solution.
Runnable task = () -> {
try {
TimeUnit.SECONDS.sleep(2);
messageBus.publishAsynch(new LegacyUiUpdateEvent());
} catch (InterruptedException e) {
// TODO Log something
Thread.currentThread().interrupt();
}
};
#Override
public void update(Observable arg0, Object arg1) {
ExecutorService executor = Executors.newSingleThreadExecutor();
if (futureTask == null || futureTask.isDone()) {
futureTask = executor.submit(task);
try {
executor.awaitTermination(10, TimeUnit.SECONDS);
executor.shutdownNow();
} catch (InterruptedException e) {
// TODO Log something
Thread.currentThread().interrupt();
}
}
}
The theory is: If future task doesn't exist, we create it, once it's there, if it's not done (because this is false legacy update 4/x where x ∈ [5,12] and the sleep is still in effect) then we completely skip and don't create a new executor.
The problem is that, from what I can tell, the executor.submit(task) does not in fact happen on a new tread. Like I said the legacy app is single threaded, and after I increased the sleep to 15s it was blindingly obvious that it was sending the whole current thread to sleep.
How would I put my taks on a completely new thread (using the concurrency library) and avoiding doing the task multiple times, even though the update method is being called way way too many times (and that is 100% out of my control). I think the future.isDone() thing works, but not 100%
if you are on Java 8 or higher, this is a better thing to do
CompletableFuture.runAsync(task);
because this will be executed on the Fork-join thread pool, that is managed by the JVM and you will not concern yourself by creating it nor shutting it down. and of course this will run asynchronously which match your requirements .
executor.submit() does start the task in a new thread, but right after executor.awaitTermination(10, TimeUnit.SECONDS); is waiting in the current thread for the task to be completed. There's no need to wait in the current thread, but there does need to be a way to determine if the task is already running.
The messy part is creating the ExecutorService each time - there's no need to recreate it each time. It can be an instance variable of the class and re-used. Ideally, it would be injected through a constructor so the class which created it can shut it down if that's really needed.
private final ExecutorService executor = Executors.newSingleThreadExecutor(); // or injected through constructor
private Future<?> futureTask;
#Override
public void update(Observable arg0, Object arg1) {
if (futureTask == null || futureTask.isDone()) {
futureTask = executor.submit(task);
}
}
I am trying to use a Third Party Internal Library which is processing a given request. Unfortunately it is synchronous in nature. Also I have no control on the code for the same. Basically it is a function call. This function seems to a bit erratic in behavior. Sometimes this function takes 10 ms to complete processing and sometimes it takes up to 300 secs to process the request.
Can you suggest me a way to write a wrapper around this function so that it would throw an interrupted exception if the function does not complete processing with x ms/secs. I can live with not having the results and continue processing, but cannot tolerate a 3 min delay.
PS: This function internally sends an update to another system using JMS and waits for that system to respond and sends apart from some other calculations.
Can you suggest me a way to write a wrapper around this function so that it would throw an interrupted exception if the function does not complete processing with x ms/secs.
This is not possible. InterruptException only gets thrown by specific methods. You can certainly call thread.stop() but this is deprecated and not recommended for a number of reasons.
A better alternative would be for your code to wait for the response for a certain amount of time and just abandon the call if doesn't work. For example, you could submit a Callable to a thread pool that actually makes the call to the "Third Party Internal Library". Then your main code would do a future.get(...) with a specific timeout.
// allows 5 JMS calls concurrently, change as necessary or used newCachedThreadPool()
ExecutorService threadPool = Executors.newFixedThreadPool(5);
...
// submit the call to be made in the background by thread-pool
Future<Response> future = threadPool.submit(new Callable<Response>() {
public Response call() {
// this damn call can take 3 to 3000ms to complete dammit
return thirdPartyInternalLibrary.makeJmsRequest();
}
});
// wait for some max amount of time
Response response = null;
try {
response = future.get(TimeUnit.MILLISECONDS, 100);
} catch (TimeoutException te) {
// log that it timed out and continue or throw an exception
}
The problem with this method is that you might spawn a whole bunch of threads waiting for the library to respond to the remote JMS query that you would not have a lot of control over.
No easy solution.
This will throw a TimeoutException if the lambda doesn't finish in the time allotted:
CompletableFuture.supplyAsync(() -> yourCall()).get(1, TimeUnit.SECONDS)
Being that this is 3rd party you cannot modify the code. As such you will need to do two things
Launch the execution in a new thread.
Wait for execution in current thread, with timeout.
One possible way would be to use a Semaphore.
final Semaphore semaphore = new Semaphore(0);
Thread t = new Thread(new Runnable() {
#Override
public void run() {
// do work
semaphore.release();
}
});
t.start();
try {
semaphore.tryAcquire(1, TimeUnit.SECONDS); // Whatever your timeout is
} catch (InterruptedException e) {
// handle cleanup
}
The above method is gross, I would suggest instead updateing your desing to use a dedicated worker queue or RxJava with a timeout if possible.
I'm creating a game modification that uses MySQL to get and store player data. It refreshes it's client data from the database every 4 seconds, but because it is blocking, it freezes about a second as it gets the data.
Is there any simple way to execute the command async?
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(() -> {
//Your jdbc call here
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
// Here, we can safely update the GUI
// because we'll be called from the
// event dispatch thread
MW.append(foo);
}
});
});
If you are not doing so already, use Threads. Override the run() method for things you want to run asynchronously in Java.
Also just making sure, you wait until the server returns the database data before performing another request right?
How to kill the thread?
.....
How to restart them again in multi threading?
Since your post is tagged "Java," I have a good idea of what you are saying. Let's say you start a thread by doing:
Thread foo = new Thread(someRunnable);
foo.start();
Now that destroy and friends are deprecated, you need a way to kill the thread. Luckily for you, there has always been the concept of "interrupts." Simply change your runnable so that, on interrupt, it exits. Then call the thread's interrupt method.
foo.interrupt();
If you wrote your Runnable to handle this correctly, it will stop whatever it is doing and terminate.
Thread.stop() kills a thread, but you definitely don't want to do this (see the API documentation for an explanation why). Thread.interrupt() sends an asynchronous notification to a thread, so that it can shut itself gracefully.
For a comprehensive text on Java multithreading, I recommend B. Goetz, Java Concurrency in Practice, Addison-Wesley Professional.
The preferred way for a Thread to die is for the execution of the run method to go to completion:
Thread t = new Thread(new Runnable() {
public void run() {
// Do something...
// Thread will end gracefully here.
}
}
Once a thread gracefully dies in the example above, the Thread cannot be restarted. (Trying to call Thread.start on a thread that has already been started will cause an IllegalThreadStateException.)
In that case, one can make another instance of the thread and call start on that.
Probably a good place to get more information on threading would be Lesson: Concurrency from The Java Tutorials.
i wrap my worker threads up in their own class and use a terminated property to kill the thread proc loop.
sorry i dont have a java version to hand right now but you should get the idea from this
http://pastie.org/880516
using System.Threading;
namespace LoaderDemo
{
class ParserThread
{
private bool m_Terminated;
private AutoResetEvent m_Signal;
private string m_FilePath;
...
public ParserThread(AutoResetEvent signal, string filePath)
{
m_Signal = signal;
m_FilePath = filePath;
Thread thrd = new Thread(this.ThreadProc);
thrd.Start();
}
public bool Terminated {
set { m_Terminated = value; }
}
private Guid Parse(ref string s)
{
//parse the string s and return a populated Guid object
Guid g = new Guid();
// do stuff...
return g;
}
private void ThreadProc()
{
TextReader tr = null;
string line = null;
int lines = 0;
try
{
tr = new StreamReader(m_FilePath);
while ((line = tr.ReadLine()) != null)
{
if (m_Terminated) break;
Guid g = Parse(ref line);
m_GuidList.Add(g);
lines++;
}
m_Signal.Set(); //signal done
}
finally
{
tr.Close();
}
}
}
}
The best way to kill a thread is to set up a flag for the thread to watch. Program the thread to exit when it sees the flag is set to true. There's no way to restart a killed thread.
If you want to start, stop, restart threads at will, maybe using the Java 5 concurrency package would be a good idea. You can have an Executor that will do a bit of work, and when you need that bit of work to be done again, you can just re-schedule it to be done in the executor.
Regarding your first query on killing thread:
You can find more details about topic in below SE questions:
How to properly stop the Thread in Java?
How can I kill a thread? without using stop();
How to start/stop/restart a thread in Java?
Regarding your second query of re-starting thread, it's not possible in java.
You can find below details in documentation page
public void start()
Causes this thread to begin execution; the Java Virtual Machine calls the run method of this thread.
The result is that two threads are running concurrently: the current thread (which returns from the call to the start method) and the other thread (which executes its run method).
It is never legal to start a thread more than once. In particular, a thread may not be restarted once it has completed execution.
Instead of plain Threads, you can use advanced concurrent API for thread life cycle management. Have a look at this post for ExecutorService details :
How to properly use Java Executor?