JBoss OrderedExecutor + CountDownLatch don't work as I expect? - java

Playing with OrderedExecutor, I tried using the CountDownLatch to start all the submitted tasks at the same time, but the tasks don't start, they're frozen.
Am i missing something?
import org.jboss.threads.OrderedExecutor;
final CountDownLatch taskUnfreezer = new CountDownLatch(1);
OrderedExecutor orderedExec = new OrderedExecutor(JBossExecutors.directExecutor(),10,JBossExecutors.directExecutor()) ;
orderedExec.executeNonBlocking(
new Runnable() {
#Override
public void run() {
try {
taskUnfreezer.await();
System.out.println("Task 1");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
orderedExec.executeNonBlocking(
new Runnable() {
#Override
public void run() {
try {
taskUnfreezer.await();
System.out.println("Task 2");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
// Try to start all tasks
taskUnfreezer.countDown();

You are using JBossExecutors.directExecutor(). This executor does not execute things in a separate thread, but instead executes tasks in the thread that calls execute (this is useful for testing).
Your code block on the first call to orderedExec.executeNonBlocking, since that is calling taskUnfreezer.await() in the same thread, and you will never get to taskUnfreezer.countDown()

Related

Use JAVA timer in the background without causing any lag in the UI

I am making a java application that send data automatically to my remote server.
What i need is to insert data without feeling lag to the end user. the remote db update part should be run in the background. i tried swingworker, thread but nothing worked. still lags my app. here is what i have done so far
public class uploader extends Thread {
static Socket socket;
static Timer ttt;
public void run() {
try {
ttt = new Timer(15000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
try {
socket = new Socket("192.168.10.1", 3306);
//upload
ResultSet rs = DB.search("select query,id FROM general_log where state = 0 order by id asc");
while (rs.next()) {
try {
socket = new Socket("192.168.10.1", 3306);
DB2.acknowledge(rs.getString(1));
DB.acknowledge("update general_log set state = 1 where id = '" + rs.getString(2) + "'");
} catch (Exception e1) {
e1.printStackTrace();
System.out.println("error");
break;
}
}
} catch (Exception e3) {
System.out.println("error");
e3.printStackTrace();
}
}
});
ttt.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
And i run it on the start up
Thread upl = new Thread(new uploader());
upl.start();
every 15 second local data should upload to the remote server. but in here my UI lags ever 15 sec when the timer runs.
how can i do it without causing a lag?
Thanks in advance.
You could optimize your SQL query with index, that's for sure.
Besides regarding main question wouldn't it be better to use Timer Task that starts up in new Handler() ?
===========================================
for example instead of class create a method:
private final Handler handler = new Handler();
private TimerTask timerTask;
private Timer timer = new Timer();
...
public void sendBackgroundData() {
timerTask = new TimerTask() {
#Override
public void run() {
handler.post(() -> {
DO YOUR CODE
}
});
}
};
timer.schedule(timerTask, 0, 2000);
}

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");
}

Starting background service in new thread freezes main application

I'm using a button to start a background service in my app. This is the code I'm using:
#Override
public void actionPerformed(ActionEvent action) {
if (action.getActionCommand().equals("Start")) {
while (true) {
new Thread(new Runnable() {
public void run() {
System.out.println("Started");
}
}).start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
This does update the service every second, which it what I want. Problem is it freezes the rest of the application. How do I implement it so that that doesn't happen?
The following is likely to cause your application to pause:
while (true) {
...
}
Try removing those lines.
Edit: as per comment, to make the newly-launched thread fire every second, move the sleep and while loop inside the run() method:
if (action.getActionCommand().equals("Start")) {
new Thread(new Runnable() {
public void run() {
while (true) {
System.out.println("Started"); }
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
You're calling this method in the Thread that updates the GUI, and this you're pausing the GUI refresh. Spawn a new thread and execute that there.
an infinite loop ??
while (true) {.....}
how you supposed to get out of here -
add an print statement inside loop and you will come to know that you have been stuck here after button click
Ok I got it. Here's what I should have done:
#Override
public void actionPerformed(ActionEvent action) {
if (action.getActionCommand().equals("Start")) {
new Thread(new Runnable() {
public void run() {
while (true) {
System.out.println("Started");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}

Safe way to replace AWT EventQueue in running Swing application

Various sporadic problems in the Swing application I maintain appear to be caused by the way it replaces the default AWT event queue with its own custom version using Toolkit.getDefaultToolkit().getSystemEventQueue().push(new AEventQueue()). See e.g. Threading and deadlock in Swing application. The problem described there has been resolved, but my tests (using FEST Swing) now tend to run into deadlock.
I suspect the best solution would be to replace the event queue at the beginning of the application initialization, before any Swing components are created. However, there are some dependencies that make that awkward so for the time being I am trying to find a safe way of "pushing" the new event queue after initialization, where it is currently done.
The two approaches I have tried are
push the new queue on the EDT using SwingUtilities.invokeLater();
push the new queue on the main thread after initialization, and after using invokeLater() to avoid deadlock with anything already started on the old EDT.
What I would expect, after reading https://stackoverflow.com/a/8965448/351885, is that the first approach might work in Java 7 but something like the second might be needed in Java 1.6. Indeed the second does work in Java 1.6, while in Java 7 both appear to complete successfully but run very very slowly. This may just be a FEST issue since the application itself seems quite responsive.
So I'm pretty much forced to use the second approach, which at least works in Java 1.6, but I would like to know
- if there is a safer way to implement this, since it seems it might be vulnerable to a race condition if an event appears on the existing queue after invokeLater but before the new queue is created;
- if there is a different approach I should use instead.
More detail
The first "solution" looks like this:
initApplication();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
Toolkit.getDefaultToolkit().getSystemEventQueue().push(new CustomEventQueue());
}
});
When compiled and run using Java 1.6, I don't understand what it is doing. It seems the thread is waiting for a lock that it already holds:
"AWT-EventQueue-1" prio=10 tid=0x00007f9808001000 nid=0x6628 in Object.wait() [0x00007f986aa72000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000007d9961cf0> (a atlantis.gui.AEventQueue)
at java.lang.Object.wait(Object.java:502)
at java.awt.EventQueue.getNextEvent(EventQueue.java:490)
- locked <0x00000007d9961cf0> (a atlantis.gui.AEventQueue)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:247)
The second "solution" looks like this:
initApplication();
try {
SwingUtilities.invokeAndWait(new Runnable() {
#Override
public void run() {
logger.debug("Waiting for AWT event queue to be empty.");
}
});
} catch (InterruptedException e) {
logger.error("Interrupted while waiting for event queue.", e);
} catch (InvocationTargetException e) {
logger.error("Error while waiting for event queue.",e);
}
Toolkit.getDefaultToolkit().getSystemEventQueue().push(new CustomEventQueue());
As stated above, this seems to work OK in Java 1.6 but I'm not convinced it is really safe.
I haven't figured out what is happening when using Java 7, but the main thread seems to spend a long time sleeping the method org.fest.swing.timing.Pause.pause(), which is why I suspect this may be a FEST-specific problem.
Because I can't see reason to reset current EDT with fresh one, my questions are
1) are you got some of
Java deallock, outofmemory ...
RepaintManager exceptions,
2) basically you can
lock current EDT with Thread.sleep(int), with setVisible(false) for caused JComponent,
if is there EDT then you have to use invokeLater, if isn't active then you can choose betweens invokeLater of invokeAndWait
code
if (EventQueue.isDispatchThread()) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
//some stuff
}
});
} else {
try {
SwingUtilities.invokeAndWait(new Runnable() {
#Override
public void run() {
//some stuff
}
});
} catch (InterruptedException ex) {
Logger.getLogger(IsThereEDT.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvocationTargetException ex) {
Logger.getLogger(IsThereEDT.class.getName()).log(Level.SEVERE, null, ex);
}
}
3) notice invokeAndWait must be called out of EDT, othewise caused EDT exceptions with deallock of current EDT
4) if isn't there active EDT, then there isn't reason push() something to the EventQueue
5) simple testing code for all above mentioned ..
import java.awt.EventQueue;
import java.lang.reflect.InvocationTargetException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
public class IsThereEDT {
private ScheduledExecutorService scheduler;
private AccurateScheduledRunnable periodic;
private ScheduledFuture<?> periodicMonitor;
private int taskPeriod = 30;
private SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
private Date dateRun;
private JFrame frame1 = new JFrame("Frame 1");
public IsThereEDT() {
scheduler = Executors.newSingleThreadScheduledExecutor();
periodic = new AccurateScheduledRunnable() {
private final int ALLOWED_TARDINESS = 200;
private int countRun = 0;
private int countCalled = 0;
private int maxCalled = 10;
#Override
public void run() {
countCalled++;
if (countCalled < maxCalled) {
if (countCalled % 3 == 0) {
/*if (EventQueue.isDispatchThread()) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
//some stuff
}
});
} else {
try {
SwingUtilities.invokeAndWait(new Runnable() {
#Override
public void run() {
//some stuff
}
});
} catch (InterruptedException ex) {
Logger.getLogger(IsThereEDT.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvocationTargetException ex) {
Logger.getLogger(IsThereEDT.class.getName()).log(Level.SEVERE, null, ex);
}
}*/
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
System.out.println("Push a new event to EDT");
frame1.repaint();
isThereReallyEDT();
}
});
} else {
if (this.getExecutionTime() < ALLOWED_TARDINESS) {
countRun++;
isThereReallyEDT(); // non on EDT
}
}
} else {
System.out.println("Terminating this madness");
System.exit(0);
}
}
};
periodicMonitor = scheduler.scheduleAtFixedRate(periodic, 0, taskPeriod, TimeUnit.SECONDS);
periodic.setThreadMonitor(periodicMonitor);
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
isThereReallyEDT();
frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame1.getContentPane().add(new JLabel("Hello in frame 1"));
frame1.pack();
frame1.setLocation(100, 100);
frame1.setVisible(true);
}
});
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
Logger.getLogger(IsThereEDT.class.getName()).log(Level.SEVERE, null, ex);
}
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame2 = new JFrame("Frame 2");
frame2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame2.getContentPane().add(new JLabel("Hello in frame 2"));
frame2.pack();
frame2.setLocation(200, 200);
frame2.setVisible(true);
isThereReallyEDT();
}
});
}
private void isThereReallyEDT() {
dateRun = new java.util.Date();
System.out.println(" Time at : " + sdf.format(dateRun));
if (EventQueue.isDispatchThread()) {
System.out.println("EventQueue.isDispatchThread");
} else {
System.out.println("There isn't Live EventQueue.isDispatchThread, why any reason for that ");
}
if (SwingUtilities.isEventDispatchThread()) {
System.out.println("SwingUtilities.isEventDispatchThread");
} else {
System.out.println("There isn't Live SwingUtilities.isEventDispatchThread, why any reason for that ");
}
System.out.println();
}
public static void main(String[] args) {
IsThereEDT isdt = new IsThereEDT();
}
}
abstract class AccurateScheduledRunnable implements Runnable {
private ScheduledFuture<?> thisThreadsMonitor;
public void setThreadMonitor(ScheduledFuture<?> monitor) {
this.thisThreadsMonitor = monitor;
}
protected long getExecutionTime() {
long delay = -1 * thisThreadsMonitor.getDelay(TimeUnit.MILLISECONDS);
return delay;
}
}

Categories

Resources