Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何通过所有线程发送消息?_Java_Multithreading - Fatal编程技术网

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
上有一个易失性字符串实例变量,implement
notify
设置volatile变量的值,让线程检查并对其值执行操作如何将ExecutorService与Runnable或Callable一起使用?这是一种已知的模式:actors。您可以查看更多信息。看起来有点像生产者消费者。您可以在
ServerThread
上有一个易失性字符串实例变量,实现
notify
来设置volatile变量的值,让线程检查并对其值执行操作如何将ExecutorService与Runnable或Callable一起使用?嘿,这正是我所做的。目前,我已经创建了一个列表来添加所有正在运行的线程,或者如您所说的EchoService,并且在它们结束时,我也将删除它们。现在我的问题是,一旦我从客户那里得到一个特定的回复,我如何能够通过所有EchoService广播一条消息。你能给我提供一种方法,可以循环所有存储的EchoServices,并通过其特定的套接字和OutputStream发送消息吗?我再次添加了相同的示例,但包括广播功能,方法在名为broadCastMsg的服务器类中,我如何控制ArrayList在服务类中。这正是我所做的。目前,我已经创建了一个列表来添加所有正在运行的线程,或者如您所说的EchoService,并且在它们结束时,我也将删除它们。现在我的问题是,一旦我从客户那里得到一个特定的回复,我如何能够通过所有EchoService广播一条消息。你能给我提供一种方法,可以循环所有存储的EchoServices,并通过它们特定的套接字和输出流发送消息吗