I would like to start off by saying that if you know a better way to do this, please tell me. I would rather know a better way of doing this than doing it incorrectly.
I am writing a server program that has to interact with multiple clients. I am using the method that this answer proposed. (socket programming multiple client to one server). I am creating the new Instance of the 'EchoThread'.
I also have another class that has a number of variables that need to be able to be accessed and changed by ALL the classes / operations in my server. I am wondering how I inject (I think that is what it's called) the Instance of that from the class creating the new 'EchoThread' object and the 'EchoThread' Class.
Part of the answer from the link above:
while (true) {
try {
socket = serverSocket.accept();
} catch (IOException e) {
System.out.println("I/O error: " + e);
}
// new threa for a client
new EchoThread(socket).start();
}
I have the Instance of the class I want to inject:
VarsClass vars = new VarsClass();
I normally "link" these by doing thing:
VarsClass vars = new VarsClass();
ExampleClass example = new ExampleClass();
example.link(vars);
Here is the 'link' method in the 'ExampleClass'
public void setGlobalVariables(GlobalVariables global) {
this.globalVariables = global;
}
How do I reference the 'EchoThread' like I do in the above example with 'ExmapleClass' and 'VarsClass'? I am doing this, so each class is not creating a new instance of the VarsClass. (Avoiding the problem I had here: Using the same variables in two threads, but I don't know why they won't update in Java)
Thank you to every one in advance for your patience and help.
~Rane
How do I reference the EchoThread ...
The simple way is like this:
EchoThread et = new EchoThread(socket);
et.link(vars);
et.start();
Or pass the vars object as another argument to the constructor.
Note that the following variant is wrong ... unless you make EchoThread thread-safe.
EchoThread et = new EchoThread(socket);
et.start();
...
et.link(vars);
(It is safe to pass the argument prior to the start() call because there is an explicit "happens before" on the start() call ... between the thread that calls start() and the starting of new thread's run() method.)
The other thing to note is that writing subclasses of Thread is generally considered to be a poor way of implementing multi-threading. A better way is to implement your thread's logic as a Runnable; e.g.
public class MyRunnable implements Runnable {
// thread state variables here ...
public MyRunnable(Socket sock, GlobalVariables vars) {
...
}
public void run() {
// thread logic goes here ...
}
}
and the use it like this:
new Thread(new MyRunnable(sock, vars)).start();
This approach allows you to easily change your code to use a thread pool or an Executor instead of a Thread that you create on the fly. (Creating threads on the fly tends to be expensive.)
You can do it the same way as with instances of any other class.
EchoThread thread = new EchoThread(socket);
thread.setGlobalVariables(globalVars);
thread.start();
Related
I have this issue I have no idea how to resolve and I'm at the brink of insanity. Programming, eh? :/
Anyway, I have a server which has a thread to send users all the info it needs to (which needs to run constantly) and another thread that awaits new server connections. My problem is once socket.accept() is called, the other thread doesn't execute.
So, to explain with code:
class Thread1 extends Thread {
public void run() {
while(true)
{
s=socket.accept();
}
}
class Thread2 extends Thread {
public void run() {
//do stuff
System.out.println("spam");
}
}
public static void main(String[] args)
{
Thread1 t1 = new Thread1();
t1.start();
t1.Thread2 t2 = t1.new Thread2();
t2.start();
}
}
Assume all other required member variables are present, no compile errors and connection functionality works fine. Just 'Thread2' executes only once.
So my question is, how do I resolve this problem?
Thanks in advance,
Tim.
I think you have a basic misunderstanding of threads. Let's see if we can clear that up.
Threads are simply another pipeline of execution. Think of them like tasks with a particular set of instructions. Once the task is done, the thread returns. Pretty simple idea, right?
In your example, Thread1 has an endless loop, which makes sense that it does run infinitely and does accept clients indefinitely.
However, Thread2 simply outputs some text and returns. There's nothing telling it to 'keep spinning'.
Within your main(), even though Thread2 is an inner class of Thread1 (which is kind of bad form to begin with, might I add) it doesn't actually force the thread to keep running.
You'll probably want to add a Queue to your server class that holds new sockets, and have Thread2 loop and check for entries.
Further Reading
Firstly, take a look at the Thread class. Its constructor takes a Runnable, so that's all you should be implementing when working with threads (i.e. class Foo implements Runnable and then new Thread(new Foo())).
If sockets are your fancy, perhaps some further reading on socket-server architecture and even about protocol design would be something you'd benefit from.
Some suggestions
never extend a Thread as it's a good way to confuse yourself. Never nest a Thread inside another Thread unless you really like confusion.
if you want to run a thread for each socket, then create a new thread for each socket in the loop.
Try the following (Note: You can add IOException handling code)
class SocketAcceptor implements Runnable {
public void run() {
while(true) {
Socket s=socket.accept();
SocketHandler sh = new SocketHandler(s);
new Thread(sh).start();
}
}
}
class SocketHandler implements Runnable {
final Socket s;
SocketHandler(Socket s) { this.s = s; }
public void run() {
System.out.println("New connection " + s);
s.close();
}
}
A better solution would be to use a Thread pool. e.g. An ExecutorService, but I would get this working first.
I am working on a relatively simple DB manager, that takes in a number of files, parses and catalogs the information in a particular fashion. I also wrote a simple GUI in Swing for this purpose. In order to speed up the process I want to implement multithreading to the parallelizable parts of the execution in order to speed up the program.
The below code sits in a class called FDBCreatePanel, a custom JPanel, that sits in a FDBManagerFrame which accommodates the main method.
private void dbCreateActionButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dbCreateActionButtonActionPerformed
jfc = new JFileChooser();
jfc.setVisible(true);
jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int returnVal = jfc.showSaveDialog(null);
((FDBManagerFrame) SwingUtilities.getRoot(this)).startProcessAnimation();
if(returnVal == JFileChooser.APPROVE_OPTION) {
new SwingWorker<Void,Void>(){
#Override
protected Void doInBackground() throws Exception {
File dir = jfc.getSelectedFile();
DbManager dbm = new DbManager(dir, dbNameField.getText());
try{
dbm.doTimeConsumingStuff();
} catch (SQLException e){
// errorhandling
}
#Override
protected void done() {
((FDBManagerFrame) SwingUtilities.getRoot(FDBCreatePanel.this)).endProcessAnimation();
}
}.execute();
}
}
The time consuming method in DbManager class leads to (among others) the following bits of code in the ParserType1 class:
private void init() {
try {
this.reader = new LineNumberReader(new FileReader(this.datfile));
Thread t = new Thread(new Runnable(){
#Override
public void run() {
Entry e;
while((e = parseNextEntry()) != null)
queue.offer(e);
}
}, "t1-parser-thread");
t.run();
} catch (FileNotFoundException e) {
// error handling
}
}
I do not see any t1-parser-thread(s) in JVisualVM when I monitor the execution of my program. It appears as if my code executes entirely on a single thread, ignoring the initiation of new threads. Am I missing something with respect to threading and Swing?
You're calling run() on the newly created Thread object in ParserType1.init(). That doesn't start a new thread - it just execute's the thread's run() method in the existing thread. You should be calling start() instead.
Fundamentally I think it was a mistake for Thread to implement Runnable at all - the distinction between "this is the code that should be executed" (Runnable) and "this is the way I'm going to execute it" (Thread) has been unfortunately blurred. The fact that Thread can also compose a Runnable makes it even worse.
Runnable runnable = new Runnable() { ... };
Thread thread = new Thread(runnable) {
// Override run here...
};
Unless your overridden run method calls super.run(), the Runnable passed into the constructor is ignored. Crazy stuff. Thread should (IMO) be final, not implement Runnable, and force you to provide a Runnable at construction. It's far too late to change now, unfortunately :(
Basically, you should never be calling run() on a Thread. At least, I can't remember the last time I saw that without it being a bug.
As Jon Pointed out you want to call the start() method to actually spawn a new Thread which will call the run method of your inline Runnable. If you just call run it is like you called any other method and it will execute in the same Thread.
}, "t1-parser-thread");
t.start();
http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html
I am using OpenCYC api (no too common, besides the point though), and I am trying to create an object AccessObject named ao. The problem is, for whatever reason, an AccessObject cannot be instantiated inside the main Java Swing Event Thread.
So as a workaround, I made another thread that just instantiates an AccessObject in it's run() method and also provides a getter for it to return it.
So this is what I have for the calling code:
// do something with code
AccessObject ao;
AccessObjectInstantiateThread aoThread = new AccessObjectInstantiationThread();
aoThread.start();
while(ao == null) // while loop to ensure we "wait" for aoThread to finish
{
ao = aoThread.getAoObject();
}
// Then use ao however you want
Now this code works, but it seems pretty rediculous. Is there any better way to do this? Remember, there is no way I can instantiate an AccessObject under the main java event thread.
Thank you very much, Rich.
Instantiate it in a SwingWorker object, and check for a valid object before completing the doInBackground() method.
Add a PropertyChangeWorker to the SwingWorker that listens for SwingWorker.StateValue.DONE, then pass the object to your Swing program.
For example,
class MySwingWorker extends SwingWorker<AccessObject, Void> {
public AccessObject doInBackground() throws Exception {
// do whatever needed to create your AccessObject and check its completion
// return your AccessObject
}
}
In your Swing code:
final MySwingWorker mySwingWorker = new MySwingWorker();
mySwingWorker.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChanged(PropertyChangeEvent pcEvt) {
if (pcEvt.getNewValue() == SwingWorker.StateValue.DONE) {
try {
ao = mySwingWorker.get(); // ao is an AccessObject class field
// you can use ao here
} catch (whaeverExceptionYouAreTrapping e) {
// do something with exception
}
}
}
});
mySwingWorker.execute();
Note, code note tested nor compiled.
Edit as per JB Nizet's recommendation you could also simply do an anonymous inner class in your Swing code and skip the PropertyChangeListener:
new SwingWorker<AccessObject, Void>() {
public AccessObject doInBackground() throws Exception {
// do whatever needed to create your AccessObject and check its completion
// return your AccessObject
}
public void done() {
try {
ao = mySwingWorker.get(); // ao is an AccessObject class field
// you can use ao here
} catch (whaeverExceptionYouAreTrapping e) {
// do something with exception
}
}
}.execute();
Your code may not work. You should at least declare your variable as follows:
volatile AccessObject ao;
The reason is, your EDT thread may cache the value of ao variable as an optimization and may not see ao is assigned to a new value.
I hope this code is at the beginning of you application and users will not see UI is not responding.
Ideally you would create AccessObject ao on the start up thread (in the main() method) and not start your UI (EventQueue.InvokeLater with a runnable containing something like new JFrame) until after you had.
Failing that, make ao volatile. Your instantiation code should set this value directly rather than bothering about a "get" method. It should probably also call InvokeLater with a runnable to readjust the display--maybe enable a button or two and send the user a message that things are now possible that were not possible before.
Any code accessing ao has to be prepared for the fact that it may be null; your GUI has to work both ways, making its situation clear to the user. Every check or reference should look something like:
final AccessObject local_ao = ao;
if (local_ao != null) {
// Do things. USE local_ao, NOT oa!!!
}
In short, always use local_ao, which won't change. Remember that the value of ao can and will change at any time. As you've described it, it will only change from null to non-null, and do so only once, but that may change as your code evolves. (If it won't evolve, my first suggestion might be best.)
Your UI (EventQueue) code should not wait for anything. Threads are pain, and I'd take a little delay in the UI over using a thread any day. But you've already paid the price for a thread, so you may as well get your money's worth.
"this" is used to refer to the members of the current class. I was trying a program in java using multithreading.
this => object of the current class where it is referred
The program is
class Thread_child implements Runnable{
Thread t;
Thread_child()
{
t = new Thread(this,"DemoThread");
System.out.println("ChildThread:"+t);
t.start();
}
public void run(){
char a[] = {'A','B','C','D','E','F','G','H','I','J'};
try{
for(int i=0;i<10;i++){
System.out.println("ChildThread:"+i+"\t char :"+a[i]);
Thread.sleep(5000);
}
}
catch(InterruptedException e){
System.out.println("ChildThread Interrupted");
}
System.out.println("Exiting from the Child Thread!");
}
}
class Thread_eg{
public static void main(String args[]){
new Thread_child();
try{
for(int i=1;i<=10;i++){
System.out.println("MainThread:"+i);
Thread.sleep(3000);
}
}
catch(InterruptedException e){
System.out.println("MainThread Interrupted");
}
System.out.println("Exiting from the Main Thread!");
}
}
What does this Thread() constructor do . why do we need to pass 'this' as a parameter to it. I tried to run it without giving the parameter but the child threads were not run.only the mainthread was printed . when i replaced the thread constructor with the parameter it ran the child threads. why is that so?
Have a look at the documentation for that constructor, and all should become clear. Pay particular attention to the part that states
If the target argument is not null, the run method of the target is called when this thread is started. If the target argument is null, this thread's run method is called when this thread is started.
(The underlying issue is that a Thread is just a thread, and doesn't inherently do anything. You need to tell it what to execute.)
Because this is the Runnable object (Thread_child) whose run() method gets called.
There are two ways of implementing a Thread. One is create a class that extends Thread class and this class runs as a thread in VM.
MyThread mt = new MyThread();
mt.start();
The start will result in execution of run method that was overridden from Thread.
In case you could not extend to Thread, you can implement Runnable which makes you implement run method. Now to run this class you need to pass an object of it to Thread.
MyRunnable mr = new MyRunnable();
Thread t = new Thread(mr); // telling the thread what needs to be execute through run method
t.start();
In your code since you are starting thread in constructor, you have passed this instead my mr in above example. Basically you need to tell Thread what it needs to do via run method.
This is how run of Thread looks like:
public void run() {
if (target != null) { //target is nothing but a Runnable.
target.run();
}
}
When you google for multi-threaded java server, most of the time you'll get a solution based on a following pattern:
public class MultiThreadServer implements Runnable {
private Socket socket;
MultiThreadServer(Socket socket) {
this.socket = socket;
}
public static void main(String args[]) throws Exception {
ServerSocket serverSocket = new ServerSocket(4444);
while (true) {
new Thread(new MultiThreadServer(serverSocket.accept())).start();
}
}
public void run() {
// ...
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
// ...
}
}
How does that relate to safe publication idioms presented in Java Concurrency in Practice?
To publish an object safely, both the
reference to the object and the
object's state must be made visible to
other threads at the same time. A
properly constructed object can be
safely published by:
Initializing an object reference from
a static initializer.
Storing a
reference to it into a volatile field.
Storing a reference to it into a final
field.
Storing a reference to it into
a field that is properly guarded by a
(synchronized) lock.
Is it really safe to use socket within run() method without any extra synchronization, is it safely published? Please do write more than just yes or no.
Yes, it's safe because start of the thread defines a happens-before relation. That is, MultiThreadServer constructor call happens-before execution of the thread's run method.
From Java Language Specification 17.4.4-17.4.5:
A call to start() on a thread happens-before any actions in the started thread
Precautions from Java Concurrency in Practice are applicable in the case when the object is made accessible to other existing threads, so they are not applicable to this case.