Block EDT till executorservice completes all task - java

In my application i have two jtextpanes and i have a executorservice instacne which contains few task. I want to assure that all the task in the executorservice instance are completed before executing the FocusListener focusGained method of any jtextpanes. Also i add some more task to the executorservice when focusLost method is called.
Code
top.addFocusListener(new FocusListener()
{
public void focusLost(FocusEvent e)
{
if (ecaViewControl.isInitialized())
{
stopRecording();
executor.execute(new Runnable()
{
public void run()
{
ecaViewControl.save(top);
}
});
executor.execute(new Runnable()
{
public void run()
{
ecaViewControl.closeDocument();
}
});
}
}
public void focusGained(FocusEvent e)
{
//Need to have completed all the task in executor service before EDT executes the code in here
});
}

if you do know the number of tasks to be finished, consider using of CountDownLatch
so your code might look like:
public void run() {
try {
// do something here
} finally {
latch.countDown()
}
}
then in the code you're waiting for tasks to complete - simply wait for latch:
latch.await();
or, instead use CompletionService if you may live without executor.

Related

Calling a method from ActionPerformed and running it on main thread

my program's UI freezes for some time after pressing a JButton. I discovered that a cause of this is a Semaphore clogging the Swing thread. This is the method containing the acquire() call on the Semaphore:
private void fetch(int numThreads) {
//some code here
sem = new Semaphore(numThreads);
for (int i = 0; i < model.getRowCount(); i++){
try {
sem.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
//some code here
}
And here is the only method that makes a call to fetch()
concFetchButt.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
switchButtonStates(false);
}
});
fetch(Integer.parseInt(threadsNumField.getText()));
}
As I understand, this code ends up running fetch() on the Swing thread, though, supposedly it has nothing to do with Swing.
I guess, my question is this: How do I run a method called from 'ActionPerformed()' of Swing on the main thread of the program instead of the Swing thread?
No need to specifically run that on the "main" thread. Simply run it on any other thread but the Swing UI thread.
The most simple solution to get there:
add an ExecutorService to your class
put that code fetch(Integer.parseInt(threadsNumField.getText())); into a Runnable object
Submit that Runnable to the ExecutorService
Along the lines of:
private final ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.execute(new Runnable() {
public void run() {
fetch(Integer.parseInt(threadsNumField.getText()));
}
});

Let ScheduledThreadPoolExecutor execute tasks on UI thread

How can I use a ScheduledThreadPoolExecutor and schedule a task which is always executed on the UI thread?
Currently, I do the following
mScheduledTask = sBackgroundExecutor.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
if (mActivity != null) {
mActivity.runOnUiThread(new Runnable() {
#Override
public void run() {
// do UI stuff
}
});
}
}
}, 0, 200, TimeUnit.MILLISECONDS);
This seems unnecessary and hard to read, but I couldn't find anything in the docs. Is it possible or is this the only way?

Why is my Thread making my JavaFX Application lag?

I'm trying to make an JavaFX application that tracks the movement of my mouse for this im using this code in the controller class:
new Thread(new Runnable() {
#Override public void run() {
while (Main.running) {
Platform.runLater(new Runnable() {
#Override
public void run() {
try {
label.setText(MouseInfo.getPointerInfo().getLocation().toString());
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
}).start();
But it couses my application to lag big time.
How should i fix this lag problem?
Thanks i fixed it:
new Thread(new Runnable() {
#Override public void run() {
while (Main.running) {
Platform.runLater(new Runnable() {
#Override
public void run() {
label.setText(MouseInfo.getPointerInfo().getLocation().toString());
}
});
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
What you doing is letting Javafx Application thread Thread.sleep(1000); <-wait
Any long term action you shoud put OUT of JFX-AT. And only update your ui components on it.
new Thread(()->{
while(Main.running){
Platform.runLater(()->{
//updateui component
//this is updating on FXAT
});
Thread.sleep(time)//This way you dont let JFXAT wait
}
}).start();
//Not sure if formatted and curly braces correctly.Bud you hopefully understand.Make sure you know which thread you let wait.Otherwise you wont be able to recieve events from paused jfxat.
You should put your Thread.sleep() call in your while loop and not in your Runnable, otherwise the loop keeps posting a lot of runLater tasks and those tasks stops the event thread for 1000ms after updating your mouse position
You call Thread.sleep(long) inside a Runnable that will be executed on the UI thread. If the thread is sleeping, it can't do anything else but sleep there. If you want your label to update every 1000 milliseconds, you can use the java.util.Timer class to make that happen.

Java - get errors propagated from background thread

I am trying to run a background service as part of my GUI application. I am using an ExecutorService and I am getting a Future back from it. This code shows what I am doing:
play.addActionListener( new ActionListener() {
service.submit(new Runnable(){ .... } }
}
Now, the submission is happening on the GUI thread, which should propagate exceptions to the main thread. Now, I don't want to block the main thread on future.get, but I would rather have some way of checking for the result of the future, so that the exceptions are proapagated to the main thread. Any ideas?
You could use a listener pattern to be notified when the background thread is done. SwingWorker for instance allows for PropertyChangeListeners to listen to the SwingWorker.State state property and you could either do this or roll your own. This is one of my favorite features of a SwingWorker.
An example....
final MySwingWorker mySwingWorker = new MySwingWorker(webPageText);
mySwingWorker.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent pcEvt) {
if (pcEvt.getNewValue().equals(SwingWorker.StateValue.DONE)) {
try {
mySwingWorker.get();
} catch (InterruptedException e) {
e.printStackTrace(); // this needs to be improved
} catch (ExecutionException e) {
e.printStackTrace(); // this needs to be improved
}
}
}
});
mySwingWorker.execute();
You can check Future.isDone() to see if it has finished, or you can have the background task perform the action e.g.
play.addActionListener( new ActionListener() {
service.submit(new Runnable(){
public void run() {
try {
// ....
} catch(Exception e) {
SwingUtils.invokeLater(new Runnable() {
public void run() {
handleException(e);
}
}
}
}
});
You could have an additional thread just to monitor the state of the future:
final Future<?> future = service.submit(...);
new Thread(new Runnable() {
public void run() {
try {
future.get();
} catch (ExecutionException e) {
runOnFutureException(e.getCause());
}
}
}).start();
And somewhere else:
public void runOnFutureException(Exception e) {
System.out.println("future returned an exception");
}

Proper way to get a Recurring Callback on the UI thread

I would like to get a recurring call back to invalidate a view. I am sure there is a neat way to do this. I am currently doing this and would like a neater / better solution if possible?
new Thread()
{
#Override
public void run()
{
while (!Thread.currentThread().isInterrupted())
{
handler.post(new Runnable()
{
public void run()
{
BannerButton.this.invalidate();
}
});
try
{
Thread.sleep(50); // yields 20 fps
} catch (InterruptedException e)
{
Thread.currentThread().interrupt();
}
}
}
}.start();
For a single shot timer on the UI thread, I do this: (But I cant find a way to do this with repeats)
(new Handler()).postDelayed(new Runnable()
{
#Override
public void run()
{
// Do stuff
}
}, SPLASH_SHOW_TIME);
Timer looked good, but it calls on a background thread.
Thanks.
Your second try using Handler is already correct. Just store the Handler and the Runnable in a field, and then inside the run() method (possibly at the end), call again
handler.postDelayed(runnable, 1000);
Look at the View.postInvalidate() method. This is different from invalidate() as you can do it from any Thread you want. It just posts an invalidate() message in the UI thread Looper
Concerning your second question simply post with some delay the same Runnable at the end of the Runnable in your Handler

Categories

Resources