In my app I have 6 Arrays which should be updated each time my main activity starts. They all updated with main thread now and this leads to degradation in my app speed. Here is my dbUpdate() function:
private void dbUpdate(){
dateDB = getDateValues();
valueDB = getValues();
catDB = getCatValues();
catIndexDB = getCatIndex();
catExpenseDB = getCatExpense();
catLimitDB = getCatLimits();
}
These arrays have no dependency on eath other and I want to update them 6 parallel thread. I read this article and tried to put each array get function in a Runnable:
Runnable run6 = new Runnable(){
#Override
public void run(){
catLimitDB = getCatLimits();
}
};
So now I have six Runnable and one Handler and I changed my dbUpdate() function:
private void dbUpdate(){
hand.post(run1);
hand.post(run2);
hand.post(run3);
hand.post(run4);
hand.post(run5);
hand.post(run6);
}
But when I run my app I feel no difference. Can someone help me with this? And I should mention that this is my first experience with multithread programming.
if you really want to run them in parrallel you might do something like this:
new Thread(run1).start();
new Thread(run2).start();
new Thread(run3).start();
..
with the handler.post you add your jobs to a queue to the hanler - and your handler might be configured to run on the UI thread - so this might not be what you want.
Related
I'm investigating making a framework to use a WebView to run arbitrary JavaScript. It works fine.
For programmer convenience I'd like to be able to make a synchronous call invoking a bit of JavaScript, and get the result within a single function (No comments please about code execution speed. Of course it'll be slow).
But the threading model is causing me problems. WebView makes its callbacks to the UI thread - which is nice and programmer-friendly. But it makes trouble for me. I'd like to be able to do this in the UI thread:
String four = X.invokeJavaScriptReturningString("2+2"); // result "4"
where the method is as follows:
public String invokeJavaScriptReturningString( final String javaScript) throws InterruptedException {
final CountDownLatch latch = new CountDownLatch(1);
final String[] result = new String[1]; // Kludge - array is assignable from nested class.
ValueCallback<String> callback = new ValueCallback<String>() {
#Override
public void onReceiveValue(String s) {
result[0] = s;
latch.countDown();
}
};
mWebView.evaluateJavascript(javaScript, callback);
latch.await(99, TimeUnit.SECONDS);
return result[0];
}
But of course the callback message gets queued in the UI thread message queue, and the function blocks for 99 seconds then returns null.
Some message-based thread models have a way to work around this; something like:
while (!latch.await(1, TimeUnit.MILLISECONDS) {
// Process any messages in the UI thread Looper queue.
}
But I can't find any way to get at the Android Looper queue.
Any suggestions how to solve this?
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().
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/
First I'd like to say that I'm working my way up from python to more complicated code. I'm now on to Java and I'm extremely new. I understand that Java is really good at multithreading which is good because I'm using it to process terabytes of data.
The data input is simply input into an iterator and I have a class that encapsulates a run function that takes one line from the iterator, does some analysis, and then writes the analysis to a file. The only bit of info the threads have to share with each other is the name of the object they are writing to. Simple right? I just want each thread executing the run function simultaneously so we can iterate through the input data quickly. In python it would b e simple.
from multiprocessing import Pool
f = open('someoutput.csv','w');
def run(x):
f.write(analyze(x))
p = Pool(8);
p.map(run,iterator_of_input_data);
So in Java, I have my 10K lines of analysis code and can very easily iterate through my input passing it my run function which in turn calls on all my analysis code sending it to an output object.
public class cool {
...
public static void run(Input input,output) {
Analysis an = new Analysis(input,output);
}
public static void main(String args[]) throws Exception {
Iterator iterator = new Parser(File(input_file)).iterator();
File output = File(output_object);
while(iterator.hasNext(){
cool.run(iterator.next(),output);
}
}
}
All I want to do is get multiple threads taking the iterator objects and executing the run statement. Everything is independent. I keep looking at java multithreading stuff but its for talking over networks, sharing data etc. Is this is simple as I think it is? If someone can just point me in the right direction I would be happy to do the leg work.
thanks
A ExecutorService (ThreadPoolExecutor) would be the Java equivelant.
ExecutorService executorService =
new ThreadPoolExecutor(
maxThreads, // core thread pool size
maxThreads, // maximum thread pool size
1, // time to wait before resizing pool
TimeUnit.MINUTES,
new ArrayBlockingQueue<Runnable>(maxThreads, true),
new ThreadPoolExecutor.CallerRunsPolicy());
ConcurrentLinkedQueue<ResultObject> resultQueue;
while (iterator.hasNext()) {
executorService.execute(new MyJob(iterator.next(), resultQueue))
}
Implement your job as a Runnable.
class MyJob implements Runnable {
/* collect useful parameters in the constructor */
public MyJob(...) {
/* omitted */
}
public void run() {
/* job here, submit result to resultQueue */
}
}
The resultQueue is present to collect the result of your jobs.
See the java api documentation for detailed information.
I'm currently working on a small game that consisted of a few targets that pop up at random for various amounts of time. The actual game will get it's I/O from a circuit board since the targets are physical.
My problem is that currently I have a java.util.Timer that fire's off every 2 seconds. Once it is triggered a random target will be displayed (which works fine so far). The problem is that I want to display the targets for a random number of seconds between 1-5 whilst the timer is still running and setting off other targets.
I get no errors and the targets display but never disappear. I guess it's some sort of Thread issue and that maybe since I'm using this.* the Target objects are just somehow getting lost in the nether! After searching around the questions here I have come up with this:
public class Target implements Runnable(){
...
public void displayFor(int seconds){
this.display();
Executors.newSingleThreadScheduledExecutor().schedule(this,time,
TimeUnit.SECONDS);
this.setDisplayed(false);
}
#Override
public void run() {
this.destroy();
}
}
Basically the initial game timer (that sets of the Targets display) calls the displayFor(2) method which runs the targets run method after the time passed. The Targets still won't disappear though.
I have tried a number of different ways of doing this like the displayFor() setting off another java.util.Timer and I also had a go at using the Quartz library (which to be honest seemed like overkill anyway) and still can't get it to work. Since there are no error messages I'm really stuck with this one.
I've haven't included a lot of the code because I don't think it's that relevant but if you guys need more information to help just let me know :)
I managed to get it working. Here's the correct code for anyone in a similar situation.
public class Target{
private Timer timer;
...
public void displayFor(int seconds) {
// send the output
BoardInterface.SetDigitalChannel(this.getId());
// calculate the delay
long time = seconds * 1000;
// create a new timer and schedule the new task
timer = new Timer();
timer.schedule(new TargetTimer(this), time);
this.setDisplayed(true);
}
}
class TargetTimer extends TimerTask{
Target target;
public TargetTimer(Target t){
this.target = t;
}
#Override
public void run() {
target.destroy();
}
}
Not sure if this is a good way of doing it but it works. If you notice anything that could be improved please let me know. Thanks guys!
Perhaps you should tell us what the display method does.
Are you un-displaying the target in the destroy/destructor code?
I'd recommend, instead of void display():
public void setDisplayed(boolean display){
if(display) {
///... do appropriate circuit output to turn on target
} else {
/// ... do appropriate circuit output to turn off target
}
}
and of course
public void run(){
setDisplayed(false);
destroy();
}