Running a function inside a thread [duplicate] - java

This question already has answers here:
Callback functions in Java
(18 answers)
Closed 2 years ago.
I'm trying to run a function inside a thread, and use the data afterwards.
The obvious problem is that the main thread isn't waiting (If that's what happens)
Though a pretty simple question, searching the internet didn't provide me any solution unfortunately.
Any advice how to implement it properly?
Thread:
MainActivity.this.runOnUiThread(new Runnable() { // A new thread to get the currencies
#Override
public void run() {
jsonConversion(mMessage);
}
Function:
public void jsonConversion(String mMessage) {
try {
JSONObject srcJson = new JSONObject(mMessage); // 2 objects, rates and base
rates = srcJson.getJSONObject("rates"); // Currencies map
baseCurrency = srcJson.getString("base"); // Base currency
lastUpdate = srcJson.getString("date"); // Last update
} catch (JSONException e) {
e.printStackTrace();
}
}

Consider using callbacks in your code to achieve what you want.
letting the program wait for a thread is not good (generally) and using asynchronous threads will not achieve what you want, because you won't get the results from the thread by the time your function is called.
So, by using callbacks, you will ensure that everything will work the way you want and methods will only be called when your parameters are ready.
Have a look at this and this answers.

Related

Queue methods in Java? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I am looking to create a pattern in Java that I am not sure how to properly accomplish... right now I have other solutions but I was wondering if there was a way to accomplish this sort of pattern
MethodArray methodarray;
public QueueSimulation(Method method){
methodarray.add(method);
}
public RunSimulation(){
methodarray.runall(); // runs all the qued methods in order
}
I have many different methods with different names that I would like to queue up.
In other words I have a class for example
Player.Moveup()
Player.Attack()
Player.FallOnGround()
World.LightsOff()
I have many different methods but I want to be able to put all these methods in an array and run them all like the pattern above.
This looks like something for which you can use a single-threaded Executor with Runnables or Callables which you create as anonymous classes.
A bit of googling led me to the Executors factory which helps create a single-threaded executor.
Here is an example:
public class MethodQueueSimulator {
Collection<Callable<Void>> methodQueue = new LinkedList<>();
ExecutorService executor = Executors.newSingleThreadExecutor();
public static void main(String args[]) throws InterruptedException {
MethodQueueSimulator simulator = new MethodQueueSimulator();
simulator.QueueSimulation(new Callable<Void>() {
#Override
public Void call() throws Exception {
System.out.println("1");
return null;
}
});
// if using java 8+, you can use lambdas instead
simulator.QueueSimulation(() -> {
System.out.println("2");
return null;
});
simulator.QueueSimulation(() -> {
System.out.println("3");
return null;
});
System.out.println("Simulation starts");
simulator.RunSimulation();
System.out.println("Simulation complete");
}
public void QueueSimulation(Callable<Void> method){
methodQueue.add(method);
}
public void RunSimulation() throws InterruptedException {
executor.invokeAll(methodQueue);
// must call shutdown, else process will not exit
executor.shutdown();
}
}
Output when run:
Simulation starts
1
2
3
Simulation complete
As you can see, the events are executed in sequential order, and the call to invokeAll is blocking, which means that code execution waits for the tasks to complete before continuing, which is why "Simulation complete" is only printed at the end. Of course, this output does not prove the claim, but try it and see for yourself.
Instead of System.out.println, you would invoke your desired methods. I did not know what sort of return values your methods have, so I opted for Void as the return type of the Callables.

How to wait for some period of time and after that just return default value?

I have below code which tells me whether my data is PARTIAL or FULL. It works fine most of the time.
public static String getTypeOfData {
DataType type = new SelectTypes().getType();
if (type == DataType.partial || type == DataType.temp) {
return "partial";
}
return "full";
}
But sometimes, this line DataType type = new SelectTypes().getType(); just hangs and it keeps on waiting forever. This code is not in my control as it is developed by some other teams.
What I want to do is if this line DataType type = new SelectTypes().getType(); takes more than 10 second (or any default number of second), my method should return back a default string which can be partial.
Is this possible to do by any chance? Any example will help me to understand better.
I am using Java 7.
The ExecutorService provides methods which allow you to schedule tasks and invoke them with timeout options. This should do what you are after, however, please pay attention since terminating threads could leave your application in an inconsistent state.
If possible, you should contact the owners of the API and ask for clarification or more information.
EDIT: As per your comment, would caching be a possibility? Meaning that on start up, or some other point, you application goes through the SelectTypes and gets their type and stores them. Assuming that these do not change often, you can save them/update them periodically.
EDIT 2: As per your other comment, I cannot really add much more detail. You would need to add a method call which would allow your application to set these up the moment it is launched (this will depend on what framework you are using, if any).
A possible way would be to make the class containing the getTypeOfData() method as a Singleton. You would then amend the class to pull this information as part of its creation mechanism. Lastly, you would then create a Map<String, Type> in which you would throw in all your types. You could use getClass().getName() to populate the key for your map, and what you are doing now for the value part.
If you are not well aware of executor service then the easiest way to achieve this is by using Thread wait and notify mechanism:
private final static Object lock = new Object();
private static DataType type = null;
public static String getTypeOfData {
new Thread(new Runnable() {
#Override
public void run() {
fetchData();
}
}).start();
synchronized (lock) {
try {
lock.wait(10000);//ensures that thread doesn't wait for more than 10 sec
if (type == DataType.partial || type == DataType.temp) {
return "partial";
}else{
return "full";
}
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
return "full";
}
private static void fetchData() {
synchronized (lock) {
type = new SelectTypes().getType();
lock.notify();
}
}
You might have to do some little changes to make it work and looks better like instead of creating new thread directly you can use a Job to do that and some other changes based on your requirement. But the main idea remains same that Thread would only wait for max 10 sec to get the response.

JavaFX SwingWorker Equivalent?

Is there a JavaFX equivalent to the Java SwingWorker class?
I am aware of the JavaFX Task but with that you can only publish String messages or a progress. I just want to call a method in the GUI thread like I would have done with the SwingWorker (by publishing messages of an arbitrary type).
Heres is an example of what I mean:
class PrimeNumbersTask extends
SwingWorker<List<Integer>, Integer> {
PrimeNumbersTask(JTextArea textArea, int numbersToFind) {
//initialize
}
#Override
public List<Integer> doInBackground() {
while (! enough && ! isCancelled()) {
number = nextPrimeNumber();
publish(number);
setProgress(100 * numbers.size() / numbersToFind);
}
}
return numbers;
}
#Override
protected void process(List<Integer> chunks) {
for (int number : chunks) {
textArea.append(number + "\n"); // HERE: execute in GUI thread
}
}
}
Solution
Thank you very much for your answers. The solution I was searching for, is to use Platform.runLater(Runnable guiUpdater).
I would rewrite your SwingWorker as follows:
class PrimeNumbersTask extends Task<List<Integer>> {
PrimeNumbersTask(TextArea textArea, int numbersToFind) {
// initialize
}
#Override
protected List<Integer> call() throws Exception {
while (!enough && !isCancelled()) {
number = nextPrimeNumber();
updateMessage(Integer.toString(number));
updateProgress(numbers.size(), numbersToFind);
}
return numbers;
}
}
Usage:
TextArea textArea = new TextArea();
PrimeNumbersTask task = new PrimeNumbersTask(numbersToFind);
task.messageProperty().addListener((w, o, n)->textArea.appendText(n + "\n"));
new Thread(task).start(); // which would actually start task on a new thread
Explanation:
Yes, we do not have a publish() method as the SwingWorker does in JavaFX, but in your case using the updateMessage() is sufficient, as we can register a listener to this property and append a new line every time the message is updated.
If this is not enough, you can always use Platform.runLater() to schedule GUI updates. If you are doing too many GUI updates and the GUI Thread is being slowed down, you can use the following idiom: Throttling javafx gui updates
Apart from the updateMessage method where you can only pass strings, there is the updateValue method where you can pass a whole object, so I believe you can use that in a similar manner. This approach is described in the "A Task Which Returns Partial Results" section of the Task documentation. Another approach is the Platform.runLater() approach mentioned also in other answer.
Note that an important difference between these approaches, is that the first one is coalescing the results, which means that for multiple frequent updateValue calls some may be omitted in order to protect flooding the FX thread.
On the other hand, the Platform.runLater approach will send all the interim results, but due to the danger of flooding the FX thread if you have high frequency updates, some additional effort may be needed to manually avoid it like #eckig suggested in his answer which points to Throttling javafx gui updates
Don't ever use SwingWorker. This piece of code in the SwingWorker.java source should be enough of an argument to not use it:
private static final int MAX_WORKER_THREADS = 10;
Instead get yourself familiar with Executor and the services that come along with it.
It has nothing to do with JavaFX, it's just plain Java. However, your question was related to JavaFX. Here's an example about how to Update UI in JavaFX Application Thread using Platform.runLater().

How to I tell when a thread is complete? [duplicate]

This question already has answers here:
How to know if other threads have finished?
(12 answers)
Closed 8 years ago.
I have a method that can take time to complete as it uses the internet to check something and depending on the internet speeds can take a while so I have placed it into its own thread but I'm wanting to know how I can notice when this thread is complete as I then need to update the screen from the Main thread.
New thread code looks like this:
Thread newThread = new Thread(){
#Override
public void run() {
//My thread code
};
newThread.start();
This is what the thread code looks like, not going to copy and paste all the code it uses as it would be pointless but I'm wanting something like when
newThread.iscomplete {
//More code
}
Something along those lines
Thanks
Maybe you can show a message at the end of the Thread. Which would be helpful to let the user know that the process has finished.
Showing Message
System.out.print("Thread has finished!");
This would be at the last line, so it would only execute if all the above codes have been executed and the code has reached the last line for execution.
Thread newThread = new Thread() {
#Override
public void run() {
//My Thread code
System.out.print("Done!");
}
};
This will print Done! in the Console (I assume application is being run using a Console). Denoting that the code has been executed.
using a variable
boolean done = false;
Thread newThread = new Thread() {
#Override
public void run() {
//My Thread code
done = true;
}
};
Using EventListeners
Or else you can use Event Listener to detect the Thread completion. The above method was kind of simple.
http://docs.oracle.com/javase/tutorial/uiswing/events/

Synchronizing Hashmap in Threading

I am facing some issues with synchronizing my idMap. This map is being used in two run() methods which are run concurrently. In the 1st run() method i'm simply mapping event id value) to response id (key). in the 2nd run() method I wish to obtain the event id (value) with that same response id (key). However, at times some event id is there and at times they can't be obtained. The program compiles just fine, but i'm no expert at threading and i believe threading is causing this idMap to be out of sync. My question is simply, how can I make idMap work smoothly and obtain the event ids as I intend to?
ConcurrentHashMap<String, String> idMap = new ConcurrentHashMap<String, String>();
ConcurrentHashMap<String, ExecutorService> executors = new ConcurrentHashMap<String, ExecutorService>();
private final class ResponderTask implements Runnable {
private ResponderTask(Event event) {
this.event = event;
}
// 1st run()
public void run() {
idMap.put(response.getId(), event.getId());
}
}//end ResponderTask
private final class QuoteTask implements Runnable {
//constructor
//2nd run()
public void run() {
IdMap.get(response.getId());
}
}//end QuoteTask
public void onResponse(final Response response) {
ExecutorService quoteExecutor = executors.get(response.getId());
if (quoteExecutor == null) {
quoteExecutor = Executors.newSingleThreadExecutor();
executors.put(event.getId(), quoteExecutor);
}
quoteExecutor.execute(new ResponderTask(event));
}
However, at times some event id is there and at times they can't be obtained. The program compiles just fine, but i'm no expert at threading and i believe threading is causing this idMap to be out of sync.
idMap is a ConcurrentHashMap which is properly synchronized and highly used and tested by many folks. If the id is not in the map when you look it up then it has not been put in there. If you explain a bit more about your code we may be able to find your problem.
For example, I don't see where the response object originates from. Is it possible that the ResponseTask is processing a different response then you expect? Is response and event supposed to be the same argument?
My question is simply, how can I make idMap work smoothly and obtain the event ids as I intend to?
It's a little hard to figure out what the proper operation of the program is supposed to be. If you are looking for the other thread to get the event you could use a BlockingQueue. Then your other thread can do a queue.take() which will wait until there is an event to process. But I'm not sure what the goal is here.
One thing that is very strange is the use of a map of ExecutorService. Do you really need multiple of them? I suspect that you really should use a single Executors.newCachedThreadPool(). Maybe, however, you want a single thread working on all requests with the same id in which case your code should work. I assume you are doing something like the following when you want to shutdown you application:
for (ExecutorService executor : executors.values()) {
executor.shutdown();
}

Categories

Resources