传递对象给线程(线程外访问对象)
Pass object to thread (access object outside thread)
我正在做一个简单的服务器-客户端系统。
服务器启动,创建一个仅存储信息的对象,然后在收到连接后,创建一个新对象,该对象运行是一个线程。
对于每个线程,我都想将第一个对象作为参数传递以更改它(add/get 信息),但我认为传递它的不是。发现它是在我第一次尝试菜单并尝试做一些事情时发现的。
已经看到一些关于这个问题的帖子,但我不知道如何将其应用于我的代码。
这是服务器代码:
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();
}
}
}
class 会做的事情:
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();
}
}
}
我在尝试访问 运行() 中的 wk.get 时注意到我的问题,它说找不到对象。
好的....您的代码中有很多问题。
- wk 永远不会保存在本地。所以后面的代码无法读取
线程已启动
- Class 是 Thread 的子类并实现
可运行。这是完全错误的。您可以扩展线程或
实施 Runnable 以有效地做到这一点。
所以我的建议是;
将构造函数更改为
Workload(Socket socket) {
this.clientes = 0; this.leiloes = 0 ; this.tid = 0;
this.socket = socket;
}
无需创建一个 Workload 对象并将其传递给另一个 Workload 对象。
这里发生了几件事。
您每次获得连接时都会创建一个新的 WorkLoad 对象。我认为您希望所有连接 share 您在程序开始时创建的 WorkLoad,但事实并非如此。
第一次连接后,您有两个 WorkLoad 对象:一个是在程序开始时创建的,另一个是您在此处创建的:
Thread t = new Thread(new WorkLoad(socket, wk));
第二个问题是如何定义 Thread 对象。
- Thread 已经实现了 Runnable,所以你不需要 "implements Runnable" 如果你已经有 "extends Thread."
- WorkLoad 是一个线程 ("extends Thread"),因此您不需要将其包装在另一个线程 ("new Thread(new Workload(...))") 中。
如果要在多个线程之间共享单个 WorkLoad,则需要将 WorkLoad(只有一个)的概念与线程(多个线程)的概念分开。
- 不要让 WorkLoad 扩展 Thread 或实现 Runnable。删除 Socket 成员。
- 创建一个新的 class(Worker?),它确实实现了 Runnable 并且具有 Socket 成员。
当您获得新连接时,请执行以下操作:
Thread t = new Thread(new Worker(socket, wk));
t.start();
我正在做一个简单的服务器-客户端系统。
服务器启动,创建一个仅存储信息的对象,然后在收到连接后,创建一个新对象,该对象运行是一个线程。
对于每个线程,我都想将第一个对象作为参数传递以更改它(add/get 信息),但我认为传递它的不是。发现它是在我第一次尝试菜单并尝试做一些事情时发现的。
已经看到一些关于这个问题的帖子,但我不知道如何将其应用于我的代码。
这是服务器代码:
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();
}
}
}
class 会做的事情:
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();
}
}
}
我在尝试访问 运行() 中的 wk.get 时注意到我的问题,它说找不到对象。
好的....您的代码中有很多问题。
- wk 永远不会保存在本地。所以后面的代码无法读取 线程已启动
- Class 是 Thread 的子类并实现 可运行。这是完全错误的。您可以扩展线程或 实施 Runnable 以有效地做到这一点。
所以我的建议是; 将构造函数更改为
Workload(Socket socket) {
this.clientes = 0; this.leiloes = 0 ; this.tid = 0;
this.socket = socket;
}
无需创建一个 Workload 对象并将其传递给另一个 Workload 对象。
这里发生了几件事。
您每次获得连接时都会创建一个新的 WorkLoad 对象。我认为您希望所有连接 share 您在程序开始时创建的 WorkLoad,但事实并非如此。
第一次连接后,您有两个 WorkLoad 对象:一个是在程序开始时创建的,另一个是您在此处创建的:
Thread t = new Thread(new WorkLoad(socket, wk));
第二个问题是如何定义 Thread 对象。
- Thread 已经实现了 Runnable,所以你不需要 "implements Runnable" 如果你已经有 "extends Thread."
- WorkLoad 是一个线程 ("extends Thread"),因此您不需要将其包装在另一个线程 ("new Thread(new Workload(...))") 中。
如果要在多个线程之间共享单个 WorkLoad,则需要将 WorkLoad(只有一个)的概念与线程(多个线程)的概念分开。
- 不要让 WorkLoad 扩展 Thread 或实现 Runnable。删除 Socket 成员。
- 创建一个新的 class(Worker?),它确实实现了 Runnable 并且具有 Socket 成员。
当您获得新连接时,请执行以下操作:
Thread t = new Thread(new Worker(socket, wk));
t.start();