Let's say I have one thread running (I'm creating many instances of this thread), and inside that I instantiate a JForm. While being inside that JForm, I call another JForm. Think of it as a multiple step registration process. When I'm inside the second form, will the previously created thread still be inside the run()? Or is the new JForm creating a new thread? I want to keep the first thread alive and access a shared resource through out the lifetime of it.
class Form1 extends JForm{
public void jButton1ActionPerformed(..){
///show Form2
}
}
class A extends Thread{
public void run() {
//show Form1
}
}
class Main {
public static void main(String args[]){
new A().start();
new A().start();
new A().start();
}
Thanks.
When you create and run your A thread, you will simply show the Form and continue executing that Thread. Separately, on the single, dedicated Swing Thread (started automatically for you) the users click will be caught and handled, resulting in a call to jButton1ActionPerformed. That code block will execute inside the Swing thread.
Hope that helps. Note that you can name your threads and always use Thread.currentThread().getName() to help you understand further what is going on in your code.
If you want to create and show a Swing component from within a non-EDT thread, you must place the Swing code in a Runnable and queue it on the event thread like so:
class A extends Thread{
public void run() {
//show Form1
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Form1 form1 = new Form1();
form1.setVisible(true);
}
});
}
}
So regardless of how many "A" objects you create, and thus separate new threads you create, all Swing code will be running on the same one thread.
Related
I have a plugin for an application containing a GUI (Swing) and is started as a thread. The GUI starts a thread that does some processing on a buttonevent, right after disposing itself. While processing, a dialog window functions as a logger. Everything works fine, the GUI and dialog window will close and the threads terminate, when calling window.dispose() after the processing finished.
Threads are started as Threads, not via SwingUtilities (I tried many times, but i just can't get that to work).
Basicly the entry class for the application:
public void calledByApplication(){
RunnableClass.startGui(this);
}
public void doStuff(){ //GUI actually gets created here
gui.setVisible(true);
}
public void calledWhenSaveButtonPressed(){
//Process some stuff
gui.dispose(); //works, thread terminates
}
RunnableClass (implements Runnable):
ApplicationEntryClass aec;
public RunnableClass(ApplicationEntryClass aec){
this.aec = aec;
}
public void run(){
aec.doStuff();
}
public static void startGui(ApplicationEntryClass aec){
Thread guiThread = new Thread(new RunnableClass(aec));
guiThread.start();
}
Gui Class:
public void calledWhenSaveButtonPressed(){
aec.calledWhenSaveButtonPressed();
}
public void calledWhenCancelButtonPressed(){
this.dispose(); //doesn't work
}
My problem:
When trying to dispose the GUI via button event (or the x with JFrame.DISPOSE_ON_CLOSE), it closes, but the thread doesn't terminate. After looking at the stack i noticed, that the EventDispatchThread gets stuck on EventDispatchThread.pumpEventForFilter(...).
I'm well aware, that the issue could be, that the thread doesn't get automatically destroyed. But since i'm new to threading i don't really know where to start troubleshooting. Any suggestions?
Edit: The dialog window is not the problem. Also, i can't use System.exit() or else the application calling the plugin will terminate.
I'm developing a cli-based custom web crawler in Java. Since it needs to have a user-friendly graphical interface for showing the result, I should add a swing frame to that involving some trees, labels, tables and so on.
That graphical interface is one of its switches, and must be started just in case user calls it. Thus, I have to start this interface in a new thread so that the application can proceed with other tasks and update components inside of GUI frame if needs.
My GUI class is some thing like:
public class Frame extends JFrame {
......
public static JLabel urlLabel;
......
public static void run() {
urlLabel = new JLabel();
urlLabel.setText("Test Url");
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Frame().setVisible(true);
}
});
}
.....
}
And, I fork it from my main class like this:
.....
if(cmd.gui){
Frame.run();
Frame.urlLabel.setText("New Url");
}
......
Unfortunately, the text of label doesn't change. I already tested repaint(), revalidate() and such other functions like these, but, nothing turned up.
I tested getText() in order to make sure it is possible to access urlLabel from main class, and it worked (I could retrieved text of label).
I was wondering how I can sort out this issue? (Basically, I need to start a swing frame in a different thread and control its components from the main thread)
Thanks in advance.
If you use invokeLater(), your Runnable will be started in the EventThread after the current operation in this thread is finished. If your label is not updated, it might be that your EventThread is busy doing something else - e.g. crawling the web.
You definitely need to make sure that your crawling work is done in another thread (start a new one, don't use the one that runs anyway, since this is most probably the EventThread). Then you might use invokeLater() in this other Thread to change the label in the EventThread.
Hint: You can check if you are in the EventThread by using SwingUtilities.isEventDispatchThread().
Remember that your data/models will be used by different threads and that this might cause problems when the data is changed in your worker thread while your GUI is trying to display it.
Thank you guys for helping.
Finally, I could overcome this obstacle by using SwingUtilities.invokeLater for updating the label's text.
I mention the approach here, since someone else might need it:
The main class:
public class Frame extends JFrame {
......
private static JLabel urlLabel;
......
public JLabel getU(){
return urlLabel;
}
public static void run() {
urlLabel = new JLabel();
urlLabel.setText("Test Url");
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Frame().setVisible(true);
}
});
}
.....
}
The GUI class:
if(cmd.gui){
Frame().run();
SwingUtilities.invokeLater( new Runnable() {
#Override
public void run() {
gui.getU().setText("New Url");
}
});
}
.....
Just a question about this manner:
Since I need to update some labels and tree nodes a couple of times during crawling, wanted to know if starting a new Runnable for each of those would be overload? If yes, how can I manage that?
---UPDATE---
According to the #xander's comment, it is possible to use lambda instead of Runnable. I think lambda doesn't have overload as much as a new object does.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I have a problem when I want to run several methods not in the main thread. I created a class extends from Runnable and put all my tasks there. There are a lot of tasks actually. Then in the main thread I created a new instance of Thread and passed my runnable class as a parameter, but what I got is that the run method is the only code which executed in the thread, and if call any method inside the runnable class it will execute in the main thread instead of the new thread.
Example:
public class ConnectionManager implements Runnable {
#Override
public void run() {
login();
}
public void login() {
//Login Logic
}
public void sendMessage() {
//Send Message Via TCP Connection
}
public void updateInfo() {
//Update Information
}
public void logOut() {
//LogOut Logic
}
}
Now I wanted to call any of these methods in another thread, so I did this:
public class Login implements SomeInterface {
private Thread thread;
private ConnectionManager connection;
public void main(String[] args) {
connection = new ConnectionManager();
thread= new Thread(connection);
thread.start(); // This will execute the run method and the login process works fine.
}
#Override
public void someCallback() {
connection.sendMessage();//this call is not executed and block the main thread !!
}
}
What am I supposed to do to run all my methods in another thread without making a new thread for each method?
You should split your logic
public class Logger implements Runnable {
#Override
public void run() {
// login logic here;
}
}
public class MessegeSender implements Runnable {
#Override
public void run() {
//Send Message Via TCP Connection
}
}
public class MessegeSender implements Runnable {
#Override
public void run() {
//Update Information
}
}
public class MessegeSender implements Runnable {
#Override
public void run() {
//LogOut Logic
}
}
And then in some client:
Runnable logger = new Logger(credentials);
Executors.newSingleThreadExecutor().execute(logger);
Well this is how threads work in java. One possibility is to use Actors in java. You will have to download the Akka framework here:http://akka.io/downloads/.
Actors works by messages, they act in a separate process and are even driven messages. In other words depending on the message you send to the actor it will process a corresponding method.
Check in the following link for instances: http://doc.akka.io/docs/akka/snapshot/java/untyped-actors.html
The method run equivalent in java actors is onReceive().
And to send a message to the actor, myActor.tell(...)
Hope this helps you!!!!
Well, that is the way threads work in Java. When You call connection.sendMessage() Your method just treats ConnectionManager and runs it's code. You need to execute Your method in another threads run(), or it will not run. Perhaps You need a way to comunicate with Your thread to make it execute a method in run() or just explore the possibilities that Future objects give You?
That's how does Runnable or Multithread handling work.
You should never call the run() directly and only this function and other function calls inside this function are executed in the new thread.
Basically your Runnable class should only contains one public function: the run() and you should not call it directly...
I suggest you to put other functions in their own classes. As you can see the workflow is not continuous, sendMessage() is not called directly after login() (otherwise you can do it inside run() and don't need that someCallback()).
Otherwise what should that new thread supposed to do in the time between? block and wait for sendMessage()? That's not a good design. So you should start a new thread for sendMessage().
Hi I'm trying to understand EDT vs. Multithreading, hoping someone could correct me if this doesn't make sense.
First I put the creating process of the GUI in its own thread which is
then added to the EDT
public class Main
{
static ServerGui serverGui;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try{
serverGui = new ServerGui();
serverGui.frame.setVisible(true);
}
catch(Exception e)
{
e.printStackTrace(); }} });}}
In my GUI I created the ServerDataHandler object sdh
public class ServerGui {
public ServerDataHandler sdh = new ServerDataHandler();
public JFrame frame;
public ServerGui() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setType(Type.NORMAL);
frame.setBounds(100, 100, 800, 600); } }
Now from another thread, I wish to work with that sdh object, and use some of the methods
that it has.. e.g. sdh.writeToFile(); so here are my questions
as I want to use the same object do I need to do it like I've down below?.
Do I need to synchronize the ServerDataHandler class when e.g. in my case the method writes down to a file? I suspect I do
When would I need to use 'invokeLater'? is that just when I'm changing in the actual GUI?
Client
public class Client implements Runnable {
private Socket clientSocket;
public Client(Socket clientSocket) {
this.clientSocket = clientSocket;
#Override
public void run() {
Main.serverGui.sdh.writeToFile();} }
Classes and objects
The Main, Client, ServerGui, and ServerDataHandler classes you have created are just that, classes. When you call a class's constructor, you create an object that is an instance of the class.
Each thread weaves its way through the objects in the JVM, following the execution path as a method in one object calls a method in another object. So objects just sit in the JVM and are not specifically bound to threads.
Threads
Also inside the JVM live multiple threads. You can create and destroy them yourself, using methods in the java.lang.Thread class. But the main thread and the The Event Dispatch Thread are created for you.
An object that's an instance of a Runnable class can be created in one thread and then handed over to be run by another thread. This is what you do when you call SwingUtilities.invokeLater. You create an anonymous Runnable object and schedule its run() method to be invoked by the Event Dispatch Thread.
Event Dispatch Thread
The reason to do this is that Swing objects are not thread-safe, i.e. not written to be handled by more than one thread at a time. Their methods, like setVisible(true) should be called by the Event Dispatch Thread, one at a time.
The event handling methods in listeners that you assign to Swing objects will be called on the Event Dispatch Thread. While they're being called, the Event Dispatch Thread is busy weaving through your event handler code, and not available to draw pixels on the screen or react to button clicks. Therefore, if you want your User Interface to be responsive, you should keep your event handling code short and quick.
If you want to run lengthy tasks, like reading a long file, or chat with the server, you should create and start a new Thread for this task to run in. This is called a Background or Worker thread. You can create a Runnable class for the job you want to run and feed it to the Thread you've created.
A somewhat more high-level way to schedule tasks is through the classes in the java.util.concurrent package, in particular the ExecutorService.
A good tutorial with more information is Concurrency in Swing
As an addition to my current application, I need to create a separate thread which will periodically do some processing
I've create a new class to do all this, and this class will be loaded on startup of my application.
This is what I have so far :
public class PeriodicChecker extends Thread
{
static
{
Thread t = new Thread(new PeriodicChecker());
while(true)
{
t.run();
try
{
Thread.sleep(5000l);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
/**
* Private constructor to prevent instantiation
*/
private PeriodicChecker()
{
}
#Override
public void run()
{
System.out.println("Thread is doing something");
// Actual business logic here, that is repeated
}
}
I want to make constructor private to prevent other people from attempting to instantiate this class accidentally. How can I achieve this?
Also, is there anything bad about my implementation of such requirements? I'm only creating one thread which will run then sleep, have I missed anything obvious? I haven't worked with threads before
Java offers ScheduledExecutorService to schedule and run periodic tasks or tasks with delay. It should provide all the features you need. Timer is another class that offers similar functionalities, but I would recommend the ScheduledExecutorService over Timer for its flexibility of configuration and better error management.
You have some conceptual erros in your code... for example:
You should call start() and not run(), because you are running the method sequentially and not simultaneously.
You can call start() only once, not once in each loop iteration. After that, the thread is in state TERMINATED, you should create a new thread to run it again
You should not create the thread in the static block, it is a bad practice, and maybe the Thread is running before you want it to run.
You should read some examples about thread, it is a little difficult to unserstand at the beginning, and you can have undesired effects very easily.
Here is a little example, that may do something similar to that you want:
public class PeriodicChecker extends Thread
{
#Override
public void run()
{
while(true) {
System.out.println("Thread is doing something");
Thread.sleep(5000);
}
}
}
public OtherClass {
public static void main(String args[]) {
Thread t = new PeriodicChecker();
t.start();
}
}
If you want that none can create a new Thread, you could create a singleton, so you will be sure that none is creating more threads.
I'd recommend you to consider Timer class - it provides functionality for periodic tasks execution.
Also you may take a look at "Timer & TimerTask versus Thread + sleep in Java" question discussion - there you can find some arguments and examples.
First of all to answer your specific question, you have already achieved your objective. You have declared your constructor to be private meaning no external class can call it like new PeriodicChecker().
Looking at your code however, there are a number of other problems:
Firstly, you are creating an instance of your class within its own static constructor. The purpose of a static constructor is to initialise any static state that your class may have, which instances of your class may then depend on. By creating an instance of the class within the static constructor, all of these guarantees go out the window.
Secondly, I don't think your thread is going to behave in the way you expect it to behave, primarily because you don't actually start another thread :). If you intend to start a new thread, you need to call the start() method on that thread object. Calling run() as you do does not actually create a new thread, but simply runs the run() method in the current thread.
Nowadays when you want to create a new thread to do something, the reccomended way of achieving this is to not extend Thread, but instead implement the Runnable interface. This allows you to decouple the mechanism of the thread, from the behaviour you intend to run.
Based on your requirements, I would suggest doing away with a top-level class like this, and instead create either a private inner class within your application start-up code, or even go for an anonymous inner class:
public class Main {
public static void main(String[] args) {
new Thread(new Runnable() {
#Override
public void run() {
while(true) {
System.out.println("Thread is doing something");
Thread.sleep(5000);
}
}
}).start();
}
}
It is almost never right to extend Thread. If you ever find yourself doing this, step back, take a look and ask yourself if you really need to change the way the Thread class works.
Almost all occurances where I see extends Thread the job would be better done implementing the Runnable interface or using some form of Timer.