how to run 2 threads in JFrame - java

Hi i got following problem...
I have main jframe started like this:
public static void main (String args[]){
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
Form3 myF=new Form3();
}
});
};
in the jframe i have Jpanels. On jpanel i want to start 2nd thread.
I tried it like this:
try {
while (DBAccess.haveResult("ASS"+harnessId)==null&&cancelCycle == 0) {
thread1.sleep(3*1000);
System.out.println("+++++++++");
System.out.println(DBAccess.haveResult("ASS"+harnessId));
res = DBAccess.haveResult("ASS"+harnessId);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
but I am unable to stop that thread and cant even cancel it, because main window stops reacting
to clarify my problem:
i have "Test" button on JPanel, which is starting test process. Test process consists of loop whiuch is repeating every 3 seconds, this loop checks database status. Problem is I am unable to stop this loop until the status appears in db (while condition), because window is busy after i click on "test". Even implementing runnable and putting test method into "run()" doesnt worked.
testbutton source code:
if (e.getActionCommand().equals("Test")){
run();}
run method:
#Override
public final void run() {
test();
}
test method:
Map result_row = DBAccess.addRow("ASS"+harnessId,htOperList.get(seqNumber-1).getNametestprogram(),"",null);
if(result_row.containsKey("ADDROW")){System.out.println("Record inserted" );}
Database db = null;
Map res = null;
try {
while (DBAccess.haveResult("ASS"+harnessId)==null&&cancelCycle == 0) {
thread1.sleep(3*1000);
System.out.println(DBAccess.haveResult("ASS"+harnessId));
res = DBAccess.haveResult("ASS"+harnessId);
}
} catch (InterruptedException e) {
e.printStackTrace();
}

You are blocking the event dispatch thread. Use a SwingWorker for heavy tasks. Put the main DB operation in doInBackround(), and use publish() for the interim results.
If you need to stop it before doInBackround() completes, you can use cancel(). See here for notes about that.

Related

Wait until the thread finish

I have a function that has inside thread that do something
public static void animate(int column,Image image)
{
new Thread(new Runnable() {
public void run() {
try {
/* Code */
repaint();
Thread.sleep(500);
repaint();
} catch (InterruptedException ex) {
}
}
}).start();
}
The animation function I summon in the updateBoard function and after this do i++.
I want to make the function animate not continue to I++ until the thread end
Inside animate fucntion i used repaint() function from swing, When i try to use .join() its block repaint() thread.
public static void updateBoard(int column, Image image) {
int i = 0;
animate(column,image);
i++;
}
Like this:
Thread t = new Thread(new Runnable(){...});
t.start();
t.join();
However, this is kind of pointless. If you are going to start a thread and immediately block waiting for it to finish you are NOT going to get any parallelism. You may as well just call the Runnable::run method in the current thread ... and avoid the (not insignificant!) overhead of creating / starting a thread.
You have a already existing thread executing updateBoard() method. Let this thread be T1.
You invoke animate() and create another thread, let this thread be T2. Now as per your question, you want to have T1 not run further until T2 completes the execution.
Thread.java defines a method join(), it allows one thread to wait for the completion of another. In your code it can be done like this.
static Thread animationThread = new Thread(new Runnable() {
public void run() {
try {
/* Code */
Thread.sleep(500);
} catch (InterruptedException ex) {}
}
});
public static void updateBoard(int column, Image image) {
int i = 0;
animate(column,image);
animationThread.join(); // this will make the thread executing updateBoard to wait until the completion of animationThread.
i++;
}
public static void animate(int column,Image image){
animationThread .start();
}
But now every thing runs one after the other, there is no use of having two threads in this case. This is similar to
public static void updateBoard(int column, Image image) {
int i = 0;
animate(column,image);
i++;
}
public static void animate(int column,Image image){
try {
/* Code */
Thread.sleep(500);
} catch (InterruptedException ex) {}
}
In this case also until unless animate method completes (without 2nd thread), i++ will not be executed. Hence for the use case in your question having a separate thread for animate does not make sense, it only adds to the overhead of creating a separate thread and context switching. Although having a separate thread for animation seems a good idea but for that you got to restructure the program you have so as the logic is based on parallel execution so as having multiple threads makes sense.

Making labels invisible after some time NetBeans

I am making a program in which I am supposed to make visibility of labels false after, say, 1 sec intervals
The program is pretty long and complex to quote so I am explaining it. I have an array of labels and each time a label is setVisible(false), slp() method is executed.
public void slp()
{
try{
Thread.sleep(1000);
}
catch(Exception e)
{
System.out.println(e);
}
}
But I am facing a problem. The method just increases the time of execution of thread and all the labels become invisible together at last. I need animation effect, and that is not coming.
What would be a good solution to my problem? Can a timer serve me?
First, your method slp should probably take a JLabel as argument, so you can modify the visibility of a specific label. Otherwise, the method would not know which label to hide.
Second, in order not to block the main thread (or whatever thread that class slp()), the Thread.sleep(1000) should be run in its own thread. That's why the code below uses new Thread(....).start(); to create a new thread that will do the actual work.
Third, as the waiting now is in a separate thread, changing the labels visibility must be done again on the Swing Events thread. For this, we use SwingUtilities.invokeLater() where we then set the label's visibility.
All together, the code could look like this:
public void slp(JLabel label) {
new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
SwingUtilities.invokeLater(new Runnable() {
public void run() {
label.setVisible(false);
}
});
}
}).start();
}
The code could be further "cleaned up" by using lambda-expressions as available since Java 8:
public void slp(JLabel label) {
new Thread(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
SwingUtilities.invokeLater(() -> label.setVisible(false));
}).start();
}

Stop JUnit from finishing until all other threads have been stopped

During my Unit tests, I'd like to plot some figures using Java FX. Now the problem is that as soon as the Unit test are done, the JVM and thus Java FX shut down and I am not able to inspect the generated plots (unlike in the case where the "test" is just started from the main method). So my question is, is there a way to stop JUnit from exiting before particular threads are finished, i.e. to replicate the behaviour as the test is started from the main method directly? And yes, I am aware that plotting is most likely not really something which should be done during a unit test in general.
At the moment I am doing something like this:
//#ContextConfiguration(classes = {DummyConfig.class })
//#RunWith(SpringJUnit4ClassRunner.class)
public class MainViewTest {
private boolean fromMain = false;
// starting the "test" from main does not require explicit waiting for
// for the JavaFX thread to finish .. I'd like to replicate this
// behaviour in JUnit (by configuring JUnit, not my test or application code)
public static void main(String [] args){
new MainViewTest(true).test();
}
public MainViewTest(){}
private MainViewTest(boolean fromMain){
this.fromMain = fromMain;
}
#Test
public void test() {
//do some tests....
//plot some results...
PlotStage.plotStage(new QPMApplication() {
#Override
public Stage createStage() {
Stage stage = new Stage();
StackPane root = new StackPane();
Scene scene = new Scene(root, 300, 300);
stage.setTitle("Stage");
stage.setScene(scene);
stage.setOnCloseRequest(new EventHandler<WindowEvent>(){
#Override
public void handle(WindowEvent event) {
Platform.exit();
}
});
return stage;
}
});
System.out.println("Stage started");
// how to get rid of this block (or using a countdownlatch) but
// still waiting for the threads to finish?
Set<Thread> threads = Thread.getAllStackTraces().keySet();
if (!fromMain) {
System.out.println("checking threads...");
for (Thread thread : threads) {
if (thread.getName().contains("JavaFX")) {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
The issue is here that I want to get rid of this nasty block to wait until all the JavaFX platform is explicitly exited.
I appreciate the answer regarding using a countdown latch instead of joining the Java FX thread explicitly. However this still requires me to explictly stop the current thread. However, I would rather like to "tell" JUnit somehow to wait for the JavaFX thread to finish.
So basically what I am looking for is a way to tell JUnit to wait for particular threads without any blocking code inside my test methods.
Appendix: Necessary classes for a minimal running example
public class PlotStage {
public static boolean toolkitInialized = false;
public static void plotStage(QPMApplication stageCreator) {
if (!toolkitInialized) {
Thread appThread = new Thread(new Runnable() {
#Override
public void run() {
Application.launch(InitApp.class);
}
});
appThread.start();
}
while (!toolkitInialized) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Platform.runLater(new Runnable() {
#Override
public void run() {
Stage stage = stageCreator.createStage();
stage.show();
}
});
}
public static class InitApp extends Application {
#Override
public void start(final Stage primaryStage) {
toolkitInialized = true;
}
}
}
public interface QPMApplication {
public abstract Stage createStage();
}
Use a CountDownLatch for that.
Initialize with 1.
When the Stage is closed, invoke countDown().
In the JUnit Test, call await() to wait for the Stage to be closed.
Example:
CountDownLatch cdl = new CountDownLatch(1);
// TODO show the stage and do not forget to add cdl.countDown() to your
// stage.setOnCloseRequest
cdl.await();
Alternative #1:
Use the JavaFX Junit Rule to perform all actions directly on the FX application Thread.
Alternative #2:
Use TestFX, for what I read from your updated description, it fits best.

Java operations in Swing thread

I have a problem.
Here is the code:
JButton buttonChangeServer = new JButton("Change server");
buttonChangeServer.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
getLobbies();
}
}
});
private void getLobbies() {
lobbyListModel.removeAllElements();
statusLabel.setText("Connecting...");
final ArrayList<LobbyInfo> lobbyInfos =
UserClient.getLobbies(host, action, null);
if (lobbyInfos != null) {
setLobbies(lobbyInfos);
statusLabel.setText("Sucessfully got lobby list from " + getHost());
}
else {
statusLabel.setText("Failed to connect to " + getHost());
}
}
The UserClient.getLobbies(host, action, null) method executes for a 3 seconds (timeout) if it can not establish connection.
The problem is that this two operations
lobbyListModel.removeAllElements();
statusLabel.setText("Connecting...");
are not visible while executing.
I suppose that the problem is that the method getLobbies() in actionPerformed(ActionEvent e) executes in Swing thread, and all the GUI operations are not being shown till the end of the execution of the getLobbies();
My aim is to show all the changes of GUI, before and after the execution of UserClient.getLobbies(host, action, null);. How can I manage that? Is there an easy way to show all of them? Thank you.
P.S. One of the solutions may be putting that potentionally long operation in another thread, like this:
private void getLobbies() {
lobbyListModel.removeAllElements();
statusLabel.setText("Connecting...");
new Thread(new Runnable() {
#Override
public void run() {
final ArrayList<LobbyInfo> lobbyInfos =
UserClient.getLobbies(host, action, null);
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
if (lobbyInfos != null) {
setLobbies(lobbyInfos);
statusLabel.setText("Sucessfully got lobby list from " + getHost());
}
else {
statusLabel.setText("Failed to connect to " + getHost());
}
}
});
}
}).start();
}
It works, but it is rather complicated. Are there any ways easier?
One of the solutions may be putting that potentially long operation in another thread
Yes, long operations (or blocking operations) should not execute on the EDT.
So you do need to execute the long running task on a separated Thread. Check out the section from the Swing tutorial on Worker Threads and Swing Worker for the Swing solution to this problem.
When your query finishes executing you can "publish" the results so the code is executed on the EDT when the Swing components are updated.

How to wait in loop in Vaadin?

Im trying to display series of photos on one page with time interval. In countinuos while loop i got:
while(true){
if (zmienna == fa.length) zmienna = 0;
Image obrazek = new Image("",pliki[zmienna]);
layout.replaceComponent(staryObrazek, obrazek);
obrazek.requestRepaint();
staryObrazek = obrazek;
zmienna++;
try {
Thread.sleep(2000) ;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
It showing only waiting icon, dispaying mwthod works fine without loop. Do anyone has an idea how I should fic this issue?
In all modern UI systems you will have to not suspend the main thread, but use a background thread to update the UI. Otherwise you block the whole UI.
In Vaadin 7 you can enable server push and then use a background thread to change the image every 2 seconds.
Enabling push is described in the book of vaadin https://vaadin.com/de/book/vaadin7/-/page/advanced.push.html
Your code could look like this:
public class PushyUI extends UI {
#Override
protected void init(VaadinRequest request) {
// Set first component/image
setContent(chart);
// Start the update thread
new ImgUpdThread().start();
}
class ImgUpdThread extends Thread {
#Override
public void run()
{
// Update the data for a while
while (count < 100) {
Thread.sleep(1000);
access(new Runnable() {
#Override
public void run() {
//update the UI as in your code above
}
});
}
}
It is important to use the access(...) method to sync access to the UI elements.

Categories