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();
}
}
Related
So I've been given an assignment to make my application check for customers every x seconds through multithreading with Runnable. So I jammed ScheduledExecutorService into my controller class, and the new thread gets called and that's all dandy, but whenever I try making an Alert I get an IllegalStateException.
The class:
public class Line implements Runnable
{
public Line()
{
System.out.println("I'm made");
}
#Override
public void run()
{
System.out.println("I've started");
try
{
Alert alert = new Alert(AlertType.ERROR, "Line is empty");
alert.setTitle("Error");
alert.setHeaderText("Line empty");
System.out.println("I've ended");
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
I've tried putting the whole run() function into Platform.runLater thing like so:
Platform.runLater(new Runnable() {
#Override
public void run()
{
System.out.println("I've started");
try
{
Alert alert = new Alert(AlertType.ERROR, "Line is empty");
alert.setTitle("Error");
alert.setHeaderText("Line empty");
System.out.println("I've ended");
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
But then Runnable complains there's no run().
Anyone got any idea how to do this? The code has to be called every x seconds through ScheduledExecutorService, and the alert must be made within the run() function.
You got yourself confused among two different Runnables. Your Line implements Runnable and thus have to implement run which would be executed by scheduler. But given that you want to relay UI work back to FX thread you need to pass it another Runnable implementation, a la:
public class Line implements Runnable
{
public Line()
{
System.out.println("I'm made");
}
#Override
public void run()
{
Platform.runLater(new Runnable() {
#Override
public void run()
{
System.out.println("I've started");
try
{
Alert alert = new Alert(AlertType.ERROR, "Line is empty");
alert.setTitle("Error");
alert.setHeaderText("Line empty");
System.out.println("I've ended");
} catch (Exception e) {
e.printStackTrace();
}
}});
}
}
I have created a simple HTTP server in Java by using a ServerSocket that accepts browser requests. The server is working fine without any errors. I have created a JForm using Swing that contains buttons to start and stop the server. In the start button I have added an ActionListener that runs my ServerMain class.
btnStartServer.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
try {
new Thread(new Runnable() {
public void run() {
ServerMain.main(new String[0]);
}
}).start();
} catch (Exception e) {
e.printStackTrace();
}
}});
How will I be able to create a Stop JButton which will stop the Runnable() thread?
Run the server in the context of a class that implements the cancel() method of Future<V>. SwingWorker<T,V> is such a RunnableFuture<V>; a complete example is seen here.
You don't want to just kill a thread (by using Thread.stop()). The reasons why are listed in this article.
I assume the code in ServerMain.main(String... args) runs some kind of while(condition) loop, like this:
public class ServerMain{
public static boolean condition = true;
public static void main(String... args){
while(condition){
//do stuff
}
//close sockets and other streams.
//Call Thread.interupt() on all sleeping threads
}
}
Your button should set this condition to false somehow:
stopButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
try {
new Thread() {
public void run() {
// set condition to false;
ServerMain.condition = false;
}
}.start();
} catch (Exception e) {
e.printStackTrace();
}
}
});
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.
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");
}
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()