Java 如何通过所有线程发送消息?
目前我有一个服务器和一个客户机,当客户机连接到服务器时,会创建一个线程来处理来自相应客户机的所有响应,并发送任何需要的答案。我现在的问题是,我需要能够通过每个现有线程向各自的客户端发送消息 我想这样做:Java 如何通过所有线程发送消息?,java,multithreading,Java,Multithreading,目前我有一个服务器和一个客户机,当客户机连接到服务器时,会创建一个线程来处理来自相应客户机的所有响应,并发送任何需要的答案。我现在的问题是,我需要能够通过每个现有线程向各自的客户端发送消息 我想这样做: public class ServerThread extends Thread { //ignore most of the constructor, just things i need public ServerThread(Socket socket, int threa
public class ServerThread extends Thread {
//ignore most of the constructor, just things i need
public ServerThread(Socket socket, int threadId, Manager manager) throws Exception {
try {
this.socket = socket;
this.threadId=threadId;
this.manager=manager;
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
manager.addThread(); //This should add this Thread to the Collection in the Manager class
} catch (IOException ex) {
throw new Exception("Error", ex);
}
}
public void notify(String message){
// Do something
}
//In the end of the thread i would call manager.removeThread to remove the Thread from the Collection
}
public class Manager {
private //Thread Collection here
public Manager(){
//Initialize the collection;
}
public void addThread(){
//Add thread
}
public void removeThread(){
//Remove Thread
}
}
如果这是处理此问题的可行选项,那么我需要什么集合来存储线程,以及
notify(String message)
方法是什么样的?它需要在Manager
中调用一个方法,该方法将向每个线程发送消息,对吗?我将在ServerThread中创建一个静态方法getInstance(int-threadId)
在此内部,您将创建一个同步的静态映射(请参见类集合)
在notify中,只需浏览地图并将消息发送到ServerThread实例
(注意:如果它是一个TreMap,它将按键排序)我将在ServerThread中创建一个静态方法getInstance(int-threadId) 在此内部,您将创建一个同步的静态映射(请参见类集合) 在notify中,只需浏览地图并将消息发送到ServerThread实例
(注意:如果是TreMap,则将按键排序)如果要创建多客户端服务器,通常建议在server类的主线程(或单独的线程)中,服务器将接受传入套接字(客户端)当接受每个套接字时,会创建一个新线程来为该客户机服务,最好将该服务作为一个单独的类来实现runnable或extends thread每个服务线程将等待与之关联的客户端的输入,并根据客户端的请求进行回复。 如果希望将数据广播到所有连接的客户端,则需要一个存储客户端服务对象的ArrayList,然后在其上循环,对于每个循环,您都将数据发送到一个已连接的客户端,但必须确保删除与ArrayList断开连接的客户端,否则它将开始引发异常 通常,客户机服务类具有接受的套接字、输入流和输出流 下面是一个我制作的多客户端echo服务器的示例,也许它会有所帮助
public class TcpServer {
public TcpServer(){
ServerSocket server = null;
try{
server = new ServerSocket(9991);
while(!server.isClosed()){
Socket acceptedSocket = server.accept();
EchoService service = new EchoService(acceptedSocket);
service.start();
}
}catch (IOException e){
e.printStackTrace();
} finally {
if(server!=null) {
try {
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args){
new TcpServer();
}}
这是服务类:
public class EchoService extends Thread {
private Socket acceptedSocket;
private DataInputStream is;
private DataOutputStream os;
public EchoService(Socket acceptedSocket) {
try {
this.acceptedSocket = acceptedSocket;
is = new DataInputStream(acceptedSocket.getInputStream());
os = new DataOutputStream(acceptedSocket.getOutputStream());
} catch (IOException e) {
try {
if (this.acceptedSocket != null)
acceptedSocket.close();
if(is != null)
is.close();
if(os != null)
os.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
@Override
public void run() {
super.run();
try {
while (!acceptedSocket.isClosed()) {
String usrMsg = is.readUTF();
String serverMsg = "server: "+usrMsg;
os.writeUTF(serverMsg);
os.flush();
}
} catch (IOException e) {
try {
if(this.acceptedSocket != null)
acceptedSocket.close();
if(is != null)
is.close();
if(os != null)
os.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}}
这是相同的示例,但包含了广播功能
服务器类:
package TCP;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class TcpServer {
public static ArrayList<EchoService> connectedServices;
public TcpServer(){
ServerSocket server = null;
try{
server = new ServerSocket(9991);
System.out.println("server started");
connectedServices = new ArrayList<>();
while(!server.isClosed()){
Socket acceptedSocket = server.accept();
System.out.println("client connected: "
+acceptedSocket.getInetAddress());
EchoService service = new EchoService(acceptedSocket);
service.start();
}
}catch (IOException e){
e.printStackTrace();
} finally {
if(server!=null) {
try {
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args){
new TcpServer();
}
public static void removeConnectedService(EchoService client) {
boolean removed = connectedServices.remove(client);
System.out.println("client has been removed"+
client.getAcceptedSocket().getInetAddress()+", "+removed);
}
public static void broadCastMsg(long id, String usrMsg) throws IOException {
for(EchoService client: connectedServices){
if(client.getId()!=id)
{
String serverMsg = "server broadcast: " + usrMsg;
client.getOs().writeUTF(serverMsg);
client.getOs().flush();
}
}
}
}
服务器输出:
客户端1输出:
客户端2输出:
客户端3输出:
如果要创建多客户端服务器,通常建议在server类的主线程(或单独的线程)中,服务器将接受传入套接字(客户端)当接受每个套接字时,会创建一个新线程来为该客户机服务,最好将该服务作为一个单独的类来实现runnable或extends thread每个服务线程将等待与之关联的客户端的输入,并根据客户端的请求进行回复。 如果希望将数据广播到所有连接的客户端,则需要一个存储客户端服务对象的ArrayList,然后在其上循环,对于每个循环,您都将数据发送到一个已连接的客户端,但必须确保删除与ArrayList断开连接的客户端,否则它将开始引发异常 通常,客户机服务类具有接受的套接字、输入流和输出流 下面是一个我制作的多客户端echo服务器的示例,也许它会有所帮助
public class TcpServer {
public TcpServer(){
ServerSocket server = null;
try{
server = new ServerSocket(9991);
while(!server.isClosed()){
Socket acceptedSocket = server.accept();
EchoService service = new EchoService(acceptedSocket);
service.start();
}
}catch (IOException e){
e.printStackTrace();
} finally {
if(server!=null) {
try {
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args){
new TcpServer();
}}
这是服务类:
public class EchoService extends Thread {
private Socket acceptedSocket;
private DataInputStream is;
private DataOutputStream os;
public EchoService(Socket acceptedSocket) {
try {
this.acceptedSocket = acceptedSocket;
is = new DataInputStream(acceptedSocket.getInputStream());
os = new DataOutputStream(acceptedSocket.getOutputStream());
} catch (IOException e) {
try {
if (this.acceptedSocket != null)
acceptedSocket.close();
if(is != null)
is.close();
if(os != null)
os.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
@Override
public void run() {
super.run();
try {
while (!acceptedSocket.isClosed()) {
String usrMsg = is.readUTF();
String serverMsg = "server: "+usrMsg;
os.writeUTF(serverMsg);
os.flush();
}
} catch (IOException e) {
try {
if(this.acceptedSocket != null)
acceptedSocket.close();
if(is != null)
is.close();
if(os != null)
os.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}}
这是相同的示例,但包含了广播功能
服务器类:
package TCP;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class TcpServer {
public static ArrayList<EchoService> connectedServices;
public TcpServer(){
ServerSocket server = null;
try{
server = new ServerSocket(9991);
System.out.println("server started");
connectedServices = new ArrayList<>();
while(!server.isClosed()){
Socket acceptedSocket = server.accept();
System.out.println("client connected: "
+acceptedSocket.getInetAddress());
EchoService service = new EchoService(acceptedSocket);
service.start();
}
}catch (IOException e){
e.printStackTrace();
} finally {
if(server!=null) {
try {
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args){
new TcpServer();
}
public static void removeConnectedService(EchoService client) {
boolean removed = connectedServices.remove(client);
System.out.println("client has been removed"+
client.getAcceptedSocket().getInetAddress()+", "+removed);
}
public static void broadCastMsg(long id, String usrMsg) throws IOException {
for(EchoService client: connectedServices){
if(client.getId()!=id)
{
String serverMsg = "server broadcast: " + usrMsg;
client.getOs().writeUTF(serverMsg);
client.getOs().flush();
}
}
}
}
服务器输出:
客户端1输出:
客户端2输出:
客户端3输出:
这是一种已知的模式:演员。您可以查看更多信息。看起来有点像生产者消费者。您可以在
ServerThread
上有一个易失性字符串实例变量,implementnotify
设置volatile变量的值,让线程检查并对其值执行操作如何将ExecutorService与Runnable或Callable一起使用?这是一种已知的模式:actors。您可以查看更多信息。看起来有点像生产者消费者。您可以在ServerThread
上有一个易失性字符串实例变量,实现notify
来设置volatile变量的值,让线程检查并对其值执行操作如何将ExecutorService与Runnable或Callable一起使用?嘿,这正是我所做的。目前,我已经创建了一个列表来添加所有正在运行的线程,或者如您所说的EchoService,并且在它们结束时,我也将删除它们。现在我的问题是,一旦我从客户那里得到一个特定的回复,我如何能够通过所有EchoService广播一条消息。你能给我提供一种方法,可以循环所有存储的EchoServices,并通过其特定的套接字和OutputStream发送消息吗?我再次添加了相同的示例,但包括广播功能,方法在名为broadCastMsg的服务器类中,我如何控制ArrayList在服务类中。这正是我所做的。目前,我已经创建了一个列表来添加所有正在运行的线程,或者如您所说的EchoService,并且在它们结束时,我也将删除它们。现在我的问题是,一旦我从客户那里得到一个特定的回复,我如何能够通过所有EchoService广播一条消息。你能给我提供一种方法,可以循环所有存储的EchoServices,并通过它们特定的套接字和输出流发送消息吗