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.
Related
I have a list of the socket in the main function, add a new socket when a new client connects to the server.
public static void main(String[] args) throws Exception {
// TODO code application logic here
server = new ServerSocket(port);
List<MySocket> sockets = new ArrayList<>();
//this is thread responsible to synchronizing
new SyncThread().start();
while(true){
Socket socket = server.accept();
MySocket mySocket = new MySocket(socket);
sockets.add(mySocket);
SocketThread.setSockets(sockets);
new SocketThread(mySocket).start();
}
}
Besides that, I also want to create a new thread that will synchronize the list of this socket to the client (by sending the list to clients periodically).
public class SyncThread extends Thread{
private static List<MySocket> sockets;
#Override
public void run(){
//send list sockets to client
}
}
How to I synchronize the list of the socket between the main function and SyncThread?
Make your list a synchronized list:
List<MySocket> sockets = Collections.synchronizedList(new ArrayList<>());
And then pass this as a constructor parameter to SyncThread:
new SyncThread(sockets).start(); // Need to add constructor parameter to class.
public class SyncThread extends Thread{
private final List<MySocket> sockets; // NOT static.
public SyncThread(List<MySocket> sockets) {
this.sockets = sockets;
}
...
}
Bear in mind that this doesn't make sockets synchronized for compound operations, e.g. iteration. For that, you'd need to explicitly synchronize on sockets; or choose a different type of list such as CopyOnWriteArrayList, which is inherently thread-safe (the choice depends on the read/write characteristics of how you use the list).
Additionally, it's rarely appropriate to extend Thread directly. Instead, pass it a Runnable:
new Thread(() -> { /* send list sockets to client */ }).start();
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();
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 have a class that creates multiple threads, each thread gets an socket as parameter in constructor.
I need to synchronize the threads, so that only one thread accesses the sockets streams at given time.
Here is quick draft of what I need:
class MyClass{
Socket socket;
public MyClass() {
socket = new Socket(address, port);
}
void createThread(){
Worker worker = new Worker(socket);
Thread t = new Thread(worker);
t.start();
}
void doStuff(){
InputStream is = socket.getInputStream();
/* ... */
}
}
class Worker implements Runnable{
Socket socket;
public Worker(Socket socket){
this.socket = socket;
}
#Override
public void run() {
InputStream is = socket.getInputStream();
/* ... */
}
}
Now here, potentially multiple threads can access sockets input stream at the same time, which would be very bad.
Now my question is: will synchronized keyword work for this case?
To use basic synchronization you could use the socket as the lock since it's shared by each worker.
public void run() {
synchronized (socket) {
InputStream is = socket.getInputStream();
/* ... */
}
}
If MyClass really needs to access the socket as well, perform the same synchronization in doStuff.
However, you're effectively serializing access to the socket and bypassing the multi-threaded aspect of your application since the lock is held during the entire duration of the run method.
I'm trying to use join to synchronize my code. When join is called I get exceptions in both parent and child thread
Exception in thread "thread3"
exception in thread run.
The thread runs in a Ruinable class and stores the thread in public member when the class is created. The main thread calls the join method on this public member.
the code main thread do
System.out.println(Thread.currentThread()+": waiting for 2 players");
do {
r=GetClient();
switch(r)
{
case 0: return; // exitvon a very bad error
}
} while(r==2);// loop if it was a timeout
cMyConnection thread = new cMyConnection("thread3", connection, mPlayerList, mPlayersMessages);
try {
thread.MyThread.join(); // call join
} catch (InterruptedException e) {
e.printStackTrace();
}
the class
public class Cconnection implements Runnable {
Thread runner;
ReentrantReadWriteLock readWriteLock;
Lock read;
Lock write;
boolean StopFlag;
String header;
Socket connection;
ServerSocket server;
StringBuffer request;
OutputStream out;
InputStream in;
String ClientMessage;
public cUsers mPlayerList;
public cMessages mPlayersMessages;
public Thread MyThread;
public Cconnection(String threadName, Socket connection_in , cUsers PlayerList, cMessages PlayerMessages) {
connection=connection_in;
mPlayerList=PlayerList;
mPlayersMessages=PlayerMessages;
MyThread = new Thread(this, threadName); // (1) Create a new thread.
MyThread.start(); // (2) Start the thread.
}
In the snippet you call "main thread" you create the thread but do not start it. You have to call thread.start() before calling thread.join().
Cheers,
My big question is why are you using threads if you are starting a thread and then immediately waiting for it to finish? Why not just call cMyConnection.run() from your main thread?
Also, your code in main references cMyConnection but then you list Cconnection. Maybe the problem is in cMyConnection? What does it look like?
Here are some additional comments about your question:
Your variable name for cMyConnection should probably not be thread. It is most likely not a Thread class which is what confused #KL. Maybe connection is a better name?
Whenever you are asking a question on stackoverflow, you should post the exception with the relevant lines from the stack-trace. This always helps the answerers.
I would consider adding start() and join() methods to your cMyConnection class. The idea that in the constructor for a class it forks a thread is a little unusual. At the very least you should document that in javadocs well.