Threaded Java server with inner class and final variable - java

I've written the following code to implement a Threaded Server:
ServerSocket passiveSocket = new ServerSocket(port, maxConnections);
while(true){
final Socket socket = passiveSocket.accept();
new Thread(new Runnable() {
public void run() {
//access socket as needed to communicate. E.g.:
PrintWriter writer = new PrintWriter(socket.getOutputStream());
//Finally close socket.
socket.close();
}
}).start();
}
Now this seems to work, but in reflection I do not really understand what's going on with the final socket variable socket when the next connection arrives. How is each thread associated with the socket instance which was current when starting the thread? - is the final keyword responsible for that?

Think of it this way: socket is secretly passed as an argument to the new Runnable constructor, and it's kept as a variable in the anonymous Runnable class. (That's actually how it works, at the bytecode level.)
The created Runnable object contains a reference to the one specific Socket value at its creation time, so it can close that specific socket when it's done.

When passing a final variable to an anonymous inner class, that variable is effectively stored in the anonymous class as if it was an instance variable.
The code above could be effectively translated to:
private static final class RunnableAnonSubclass implements Runnable {
private final Socket socket;
private RunnableAnonSubclass (Object socket) {
this.socket = socket;
}
public void run() {
//access socket as needed to communicate. E.g.:
PrintWriter writer = new PrintWriter(socket.getOutputStream());
//Finally close socket.
socket.close();
}
}
// ...
{
ServerSocket passiveSocket = new ServerSocket(port, maxConnections);
while(true){
Socket socket = passiveSocket.accept();
new Thread(new RunnableAnonSubclass(socket)).start();
}
}
Notice that making a local variable final is the only way to access it inside an anonymous inner class. See Jon's answer on "Why are only final variables accessible in anonymous class?" for details on the reasons.

Related

Why does this implementation of a thread work without a run method?

I have received some code through a school project and I'm failing to understand the purpose of the use of threading in this scenario. The project requires use of a multi threading server to pass. I have the following thread implementation which of a new instance is created every time a new client connects.
The problem is that they are not using the run-method, in my understanding the thread exists when it finishes running the run-method. But even after the thread should have finished running it manages to send further the messages from the propertyStateListener. Why does this work and does this really count as a multi-threaded server?
Starts an instance of the ClientHandler every time a new client connects:
#Override
public void run() {
while (true) {
MessageProducer mp;
try {
Socket socket = serverSocket.accept();
new ClientHandler(socket).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
The actual ClientHandler:
private class ClientHandler extends Thread implements PropertyChangeListener {
private Socket socket;
private ObjectInputStream ois;
private ObjectOutputStream oos;
private Message messagerecieved;
public ClientHandler(Socket socket) throws IOException {
this.socket = socket;
oos = new ObjectOutputStream(socket.getOutputStream());
ois = new ObjectInputStream(socket.getInputStream());
messageManager.registerListener(this);
}
#Override
public void propertyChange(PropertyChangeEvent evt) {
messagerecieved = (Message) evt.getNewValue();
try {
oos.writeObject(messagerecieved);
oos.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void run() {
}
}
The problem is that they are not using the run-method, in my understanding the thread [exits] when it finishes running the run-method. But even after the thread should have finished running it manages to send further the messages from the propertyStateListener.
You are correct that the code is confusing for sure. They are creating a thread with each instance of ClientHandler but there is no run() method so the thread immediately exits after start() is called. The code would actually still work if ClientHandler did not extend thread.
Why does this work
It is the messageManager thread which is calling back to the ClientHandler.propertyChange(...) method which writes the results back to the socket, not the ClientHandler thread.
does this really count as a multi-threaded server?
There certainly are 2 threads at work here because you have the socket-accept thread and the messageManager thread. Whether or not this is a "multi-threaded server" depends on the assignment I guess. Certainly if there was supposed to be a thread per client then this code does not do that.

ServerSocket in Java hangs thread, unlocks on placing a break point?

I seem to have an unusual problem that I can't understand the root cause to.
I am using a ServerSocket to handle connections to a server I'm writing. The ServerSocket accepts connections in it's own thread, and can be controlled from the main thread via isAccepting and isActive variables I set up.
What should happens:
Server starts and is accepting connections (via putty). I use a command to close the server socket. The socket closes and the thread idles (I notice this causes a SocketException that I catch). I use a command to open a new server socket and it accepts connections again. I'm able to connect and can exit the application via a command that shuts down the socket and exits the loop accepting connections
What happens:
Server starts and is accepting connections (via putty). I use a command to close the server socket. The socket closes and the thread idles(I notice this causes a SocketException that I catch). I use a command to open a new server socket and that's where the thread hangs. It does not print out any debug info that's in the code, nor does it responde to opening/closing the ServerSocket. using the Exit command hangs the application on the exit routine. Funny thing is, if I set a breakpoint anywhere in the thread code, it unstucks and completes, exiting.
TL;DR - closing the socket jams the thread until I place a breakpoint, after which the code executes normally.
Tried exporting into an executable JAR and the application hangs on exit, just like in Eclipse.
Relevant parts of code below:
public class ConnectionManager extends Thread implements IEverfreeManager {
private final int defaultPort = 8002;
private boolean isAccepting = true;
private boolean isActive = true;
private static ConnectionManager instance;
private ServerSocket serverSocket;
private int portNumber = defaultPort;
private Socket workSocket;
public static ConnectionManager instance(){
if (instance == null)
instance = new ConnectionManager();
return instance;
}
public ConnectionManager() {
}
public boolean isAccepting() {
return isAccepting;
}
public void setAccepting(boolean isAccepting) {
this.isAccepting = isAccepting;
try{
if (!isAccepting && !serverSocket.isClosed()){
serverSocket.close();
System.out.println("Closed server on port "+portNumber);
} else{
serverSocket = new ServerSocket(portNumber);
System.out.println("Server on port "+portNumber+" is now accepting connections");
}
}catch(Exception e){
System.out.println("failed to stop accepting");
e.printStackTrace();
}
}
public boolean isActive() {
return isActive || isAlive();
}
public void setActive(boolean isActive) {
this.setAccepting(isActive);
this.isActive = isActive;
}
public int getPortNumber() {
return portNumber;
}
public void setPortNumber(int portNumber) {
this.portNumber = portNumber;
}
private int getNewConnectionId(){
return ++connectionIdCounter;
}
#Override
public void run() {
super.run();
try {
System.out.println("Starting up Connection Manager");
System.out.println("Starting server on port "+portNumber);
serverSocket = new ServerSocket(portNumber);
System.out.println("Server running and ready to accept players");
while (isActive){
if (isAccepting){
try{
System.out.println("Waiting for connection...");
workSocket = serverSocket.accept();
System.out.println("Connected with "+workSocket.getInetAddress());
int id = getNewConnectionId();
} catch (SocketException e){
System.out.println("Notice: "+e.getMessage());
}
}
}
}catch(Exception e) {
e.printStackTrace();
}
}
#Override
public void closeManager() {
setActive(false);
}
Using setAccepting(false) and then setAccepting(true) doesn't produce the
System.out.println("Waiting for connection...");
message until I put a breakpoint in the code.
Using closeManager() after setAccepting(false) produces the same results.
Using just closeManager() without touching setAccepting() exits gracefully (despite having the procedure activated during shutdown)
Any insight would be very appreciated
There's nothing thread-safe in this class. There are very fundamental problems with almost every function.
Both isAccepting and isActive both need to be either volatile or be modified in a synchronized manner to be thread-safe. If another thread is calling functions that mutate these fields and you have your run method already looping over them you may get unpredictable results. Attempting to view boolean flags that have no memory visibility guarantees is always a bad idea.
setAccepting() has a race condition where your run() thread may attempt to listen on a socket that is immediately about to be closed.
The singleton ConnectionMananger instance could have multiples be created. In your case your constructor does nothing but it's generally safer to not have to create instances. Use double checked locking to implement this so only one instance will ever be created.
Your immediate problem could likely be 'fixed' by making both the is* member fields volatile but like I said you still have too many other issues in this class that it would be complete safe to use in a multithreaded environment. In addition, catching Exception and simply printing is usually wrong. And you usually want to subclass runnable and pass that to the thread constructor rather than creating a subclass of thread.

How to fire event listener from Java thread

I have thread with Socket inside. When soket receives some data, I need to fire event (using my sublassed EventObject). Event listeners is added from main thread (to some list?). is this OK?
Pseudocode:
public class SocketThread extends Thread{
private Socket socket;
private MyEventListener eventListener;
public SocketThread(Socket socket, MyEventListener eventListener) {
this.socket=socket;
this.eventListener=eventListener;
}
public void run() {
get socket input stream...
get socket output stream...
when data received, call process(data)
}
void process(data){
synchronized(this){
myEvent event=new MyEvent(data);
eventListener.fireSomeEvent(myEvent );
}
}
// main thread
ServerSocket serverSocket=new ServerSocket(host,port);
Socket socket= serverSocket.accept();
ClientThread cthr = new SocketThread (sckt,new MyEventListener(){
void fireSomeEvent(MyEvent event){
//some code
}
});
This seems perfectly fine. As long as you're not changing the eventListener there is no concurrency problem that way. But be aware that fireSomeEvent() will be ran from the SocketThread. If you're doing something that is not thread-safe there, you might (will) encounter problems. So that's where you'll need some sort of synchronization.

Communication between thread inside a thread Java

I don't know how to solve this problem I hope that you can help me.
Behind Server side I have this:
class Baza0 implements Runnable{
anotherclass arraylist_handle = new anotherclass();
public method1(string s1){uses methods figured in arraylist_handle)
public run(){
while(true){
Socket s = s.accept();
if(s==NULL) continue;
//there I'm starting another thread that handles client connection
}
}
public static void main(){
Baza0 baza0 = new Baza0();
Thread t = new Thread(baza0);
}
}
Connected clients sends Strings by socketserver feature to client handler. How can I send this string from client handler to the method1 as parameter? It must use the only one Baza0 object, because of the ArrayList that must be common for all the clients.
EDIT
can someone tell me why something like Baza0.baza0.method1() won't work?
EDIT2
Look what I did!
I've made in Class Baza0 an static variable:
static Baza0 baza1;
and in main method I've started an Baza0 object:
Baza0 baza0 = new Baza0();
after this run the method that makes baza1 = baza0.
now from client handler I have access to method, by:
Baza0.baza1.method1(param);
It does work! :D ...don't know why.
If you are using the arraylist only for reading, then all the child threads are free to access it concurrently;
if the threads want to modify the list, then the list must be thread-safe;
if the modification involves many steps (reading and writing), then you must use synchronized blocks within which a "transaction" with the list happens.
Pass a Baza0 reference to Client Handler thread which can be used for calling method1.
public method1(string s1){
synchonized(arrayList){
//list operation
}
}
...
while(true){
Socket s = s.accept();
if(s==NULL) continue;
new Thread(
new WorkerRunnable(
clientSocket, this).start();
}
....
public class WorkerRunnable implements Runnable{
public WorkerRunnable(Socket socket,Baza0 ba){
this.socket = socket;
this.baza =ba;
}
public void run(){
...
this.ba.method1(...);
}
}
Your client thread must have a reference to that ArrayList - directly or (better) indirectly. Simplest way to do this is to pass Baza0 instance (this) to the client thread:
public class Client implements Runnable {
private final Baza0 baza;
public Client(Baza0 baza) {
this.baza = baza;
}
public void run() {
//...
baza.method1("Some string");
}
}
When you create your Client thread simply pass this:
new Thread(new Client(this)).start();
Important thread safety issue: method1() has to be synchronized or your ArrayList must be thread-safe.
I'd say what #Marko Topolnik said. Also I have a book Java Concurrency In Practice (that right now is not responding to me :-() or a link that led me to the book, in the blog The Java Specialists for handling thread issues. The book has examples of all queues, concurrent, synchronized lists, ways to implement code to do several things, etc, and all pretty straight forward, an example and a few paragraphs of every subject.

Java: how to compare object in different threads

I have a server listening data from clients. Once a client sends data, it will go into a thread. Thus, each thread has a data. revFeaturePoints is the data which the server receives from clients.
Each revFeaturePoints has a float array, I want to compute the Euclidean distance between different revFeaturePoints in different thread?
I do not know how can let one thread to access another revFeaturePoints in other threads?
Here is the code:
public class MyServer {
public static void main(String[] args) throws IOException{
ServerSocket serverSocket = null;
//bind a serverSocket to the port and listen
try{
serverSocket = new ServerSocket(8888);
System.out.println("Listening: 8888");
}catch(IOException e){
e.printStackTrace();
}
while(true)
new MyServerThread(serverSocket.accept()).start();
}
}
public class MyServerThread extends Thread{
//Create a socket for each client
private Socket socket = null;
private ObjectInputStream dataInputStream = null;
private ObjectOutputStream dataOutputStream = null;
private ArrayList<FeaturePointList> revFeaturePoints = null;
//constructor
public MyServerThread(Socket socket){
super("MyServerThread");
this.socket = socket;
}
#SuppressWarnings("unchecked")
public void run(){
try{
dataOutputStream = new ObjectOutputStream(socket.getOutputStream());
dataInputStream = new ObjectInputStream(socket.getInputStream());
System.out.println("ip: "+ socket.getInetAddress());
revFeaturePoints = (ArrayList<FeaturePointList>) dataInputStream.readObject();
}catch(IOException e){
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
if(socket!=null){
try{
socket.close();
}catch(IOException e){
e.printStackTrace();
}
}
if(dataInputStream!=null){
try{
dataInputStream.close();
}catch(IOException e){
e.printStackTrace();
}
}
if(dataOutputStream!=null){
try{
dataOutputStream.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
}
}
A simple way would be putting a synchronized method in MyServerThread that returns the data.
Another way of doing it would be to use a BlockingQueue and place the data result in a queue and taking the results from this as a producer-consumer pattern. See here for a way of doing this.
If your MyServerThread class stashes the data into a field, you can access that field from multiple instances of MyServerThread.
You can share the data among threads by using a shared structure and correct synchronization. For example, you could have a ConcurrentHashMap<'threadname', data> in MyServerThread where each thread puts its data and search for data in other threads.
That said, you should evaluate your architecture. If N threads have to check what the other N-1 threads are doing with data, you are preparing a recipe for performance disaster. Probably, what you would like to do is to create some layering in your architecture, where a number of ServerThreads are gathering the request and placing them in a concurrent shared structure (e.g queues). Then another set of workers are comparing and processing the data and producing results in a collaborative system. Have a look at the producer-consumer pattern.
[really a comment but won't fit ;)]
maasg's answer is quite correct in the general sense, but I believe you are right now looking at design difficulties and not Java threaded implementation per se.
You server (as is) fires off a disposable thread on each connect request, and this thread simply reads one object from the client and then closes the connection. The passed object is put in a (server thread) instance scoped object (which is duly garbage collected after you exit run()).
It is completely unclear -- and thus the impression that this is a design problem -- how you determine which 2 threads to compare, or for that matter, what guarantees you have that there will be (always) 2 concurrent threads to begin with.
Logically, you clearly have some domain specific association between a server thread and some meaningful matter in your domain. This relationship needs to be embodied in code, but first we need to understand what is this distinction and relationship.
Objects aren't 'in different threads'. Objects are members of other different objects, usually referenced via 'get' methods. Forget about the thread issue entirely, it is irrelevant. You just want to compare a member of object A with a member of object B. This is just business as usual.

Categories