I'm doing a simple server-client system.
the server starts, creates an object that will only store info, then after it receives a connection, creates a new object that runs a thread.
For every thread i want to pass the first object as a param to alter it (add/get info) but what i thought was passing it on, is not. Discovered it on tried my first atempt to a menu and try to do stuff.
Already saw some posts regardings this issue but i couldn't figure it out how to apply to my code.
Here is the server code:
import java.io.*;
import java.net.*;
import java.net.*;
public class Servidor {
static final int PORT = 8000;
public static void main(String args[]) {
ServerSocket serverSocket = null;
Socket socket = null;
int i = 0;
//the object that will only store info
WorkLoad wk;
wk = new WorkLoad();
try {
serverSocket = new ServerSocket(PORT);
System.out.println("Leiloes do Ave 2097");
} catch (IOException e) {
e.printStackTrace();
}
while (true) {
try {
socket = serverSocket.accept();
} catch (IOException e) {
System.out.println("I/O error: " + e);
}
// new thread passing the previously created object
//new WorkLoad(socket, wk).start();
Thread t = new Thread(new WorkLoad(socket, wk));
t.start();
}
}
}
The class that will do the stuff:
import java.net.*;
import java.util.*;
import java.io.*;
import java.lang.*;
public class WorkLoad extends Thread implements Runnable {
protected Socket socket;
//private int y; //usado no menu?
private int clientes;
private int leiloes;
private int tid; //thread id
private HashMap<Integer,Cliente> lClientes; //lista de todos os clientes existentes <ID,Cliente()>
private HashMap<Integer,Leilao> lLeiloes; //lista de todos os leilões existents <ID, Leilao()>
private HashMap<Integer,String> lThreads; //lista das threads
private String[] menu = new String[10];
// the construtor of the object to store info
public WorkLoad() { this.clientes = 0; this.leiloes = 0 ; this.tid = 0;} //fazer sempre ++ ao criar
// and here what i thought would pass the object to the thread, the thread constructor
public WorkLoad(Socket clientSocket, WorkLoad wk) {
this.socket = clientSocket;
//this.tid = id;
//wk.addTid(id,"");
}
public HashMap<Integer,Cliente> getListaClientes() { return this.lClientes; }
public HashMap<Integer,Leilao> getListaLeiloes() { return this.lLeiloes; }
public void addCliente(Integer id, Cliente c) { this.lClientes.put(id,c); }
public void addLeilao(Integer id, Leilao l) { this.lLeiloes.put(id,l); }
public int getTotalLeiloes() { return this.leiloes; }
public int getTotalClientes() { return this.clientes; }
public void addTid(int id,String s) { lThreads.put(id,s); } //adiciona thread lista
public int getTid() { return this.tid; }
public String getTidMsg(int id) { return lThreads.get(id);} //devolve mensagem da lista de threads
public Leilao getLeilao(Integer id) { return this.lLeiloes.get(id); } //devolve o leilao pela id
public void run() {
PrintWriter out = null;
BufferedReader in = null;
DataOutputStream cout = null;
//private HashMap<Integer,String> lThreads;
//MENU
menu[0] = "1"; //menu de escolha menu[0] = MENU.A.APRESENTAR
menu[1] = "- Registo de utilizador - :insere o username e depois a password\n"; //tem de fazer 2 readlines
menu[2] = "- Login de utilizador - :insere o username e depois a password\n"; //tem de fazer 2 readlines
menu[3] = "- Menu geral - :1)Criar Leilao:2)Listar Leiloes:3)Licitar leilao:4)Terminar Leilao:Para sair escreva exit\n";
menu[4] = "- Licitar leilao - :Insere o id de leilao e depois o valor da tua licitação com . (ex 5.5)\n"; //tem de fazer 2 readlines
menu[5] = "- Criar leilao - :Insere a descricao do item\n";
menu[6] = "- Terminar Leilao -:Insere a id do leilao que queres terminar\n";
try {
//System.out.println(socket.getInetAddress() + " entrou.");
//ArrayList<String>
out = new PrintWriter(socket.getOutputStream());
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//v2
cout = new DataOutputStream(socket.getOutputStream());
cout.writeBytes("Bem vindo ao leilões do Ave :1) Registo :2) login :exit para sair.\n");
String input;
//cria nova instancia de cliente
Cliente clithread = new Cliente(wk.getTotalClientes());
//while((input = in.readLine()) != null) {
while(true) {
input = in.readLine(); //Lê uma linha - tem de se tratar linha a linha
if(input.equals("exit")) { in.close(); cout.close(); socket.close(); return; }
if(input.equals("1")) { } // registo cliente
//cout.writeBytes(menu[input.toString()]); //print menu registo
//input = in.readLine(); //lê username
//cout.writeBytes("Recebi a mensagem:" + input + "\n"); //POR O \n no fim ou o cliente nao funciona direito!!
//System.out.println(input); //print no server local
}
// in.close();
// out.close();
// socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I noticed my problem when i was trying to access the wk.get inside the run() and it was saying it could not find the object.
There are a couple of things going on here.
You're creating a new WorkLoad object every time you get a connection. I think that you want all of the connections to share the WorkLoad you're creating at the start of the program, but that's not what's happening.
After the first connection, you have two WorkLoad objects: the one created at the start of the program, and the one you created here:
Thread t = new Thread(new WorkLoad(socket, wk));
The second issue is how you're defining your Thread object.
If you want a single WorkLoad shared among multiple threads, you need to separate the concept of WorkLoad (of which there is only one) from the concept of a thread (of which you will have multiple).
When you get a new connection, do something like:
Thread t = new Thread(new Worker(socket, wk));
t.start();