在Java服务器中的客户端线程之间切换

在Java服务器中的客户端线程之间切换,java,multithreading,client-server,Java,Multithreading,Client Server,我正在做一个项目,试图让几个人能够控制一个机器人手臂。为此,他们必须连接到Java服务器,然后该服务器将命令发送到机器人屏幕以进行视频会议。 我试图为每个客户端设置一个线程,然后我希望能够根据声音在不同的客户端之间切换,因为我希望扬声器能够控制机器人。 客户端都提供位置数据和kinect采集的声音级别,并以字符串的形式发送到服务器。 我在执行切换时遇到问题。目前,它们似乎在来回切换,这使机器人陷入混乱 是否有一种比较线程的好方法,找到合适的线程,切换到该线程,同时检查其他线程是否或何时成为最合适

我正在做一个项目,试图让几个人能够控制一个机器人手臂。为此,他们必须连接到Java服务器,然后该服务器将命令发送到机器人屏幕以进行视频会议。 我试图为每个客户端设置一个线程,然后我希望能够根据声音在不同的客户端之间切换,因为我希望扬声器能够控制机器人。 客户端都提供位置数据和kinect采集的声音级别,并以字符串的形式发送到服务器。 我在执行切换时遇到问题。目前,它们似乎在来回切换,这使机器人陷入混乱

是否有一种比较线程的好方法,找到合适的线程,切换到该线程,同时检查其他线程是否或何时成为最合适的线程?同时检查是否有其他客户端尝试连接到服务器?

谢谢你的帮助

我还包括了我的代码,以防您想查看它并获得更好的想法

这是服务器类:

import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.Hashtable;

public class MultiThreadedServer implements Runnable {
    protected int       serverPort  = 8888;
    protected ServerSocket  serverSocket    = null;
    protected boolean   isStopped       = false;
    protected Thread        runningThread   = null;
    protected Thread        clientThread    = null;
    protected Thread        threadThread    = null;
    private Hashtable<Long, WorkerRunnable> Users = new Hashtable<Long, WorkerRunnable>();
    private ArrayList<Thread> ClientThreads = new ArrayList<Thread>();
    private WorkerRunnable  client          = null;
    private ThreadHandler   threadHandler   = null;
    private int             sound_max       = 0;
    private boolean         once            = true;

    public MultiThreadedServer (int port) {
         this.serverPort = port;
    }

    public void run() {
    synchronized(this) {
        this.runningThread = Thread.currentThread();
    }
    openServerSocket();
    threadHandler = new ThreadHandler();
    while( !isStopped() ) {
        Socket clientSocket = null;
        try {
            System.out.println(InetAddress.getLocalHost());
            clientSocket = this.serverSocket.accept();          // Connect to clients
        } catch (SocketTimeoutException e) {

        } catch (IOException e) {
            if( isStopped() ) {
                System.out.println("Server Stopped");
                return;
            }
            throw new RuntimeException("Error accepting client connection", e);
        }

        client = new WorkerRunnable(clientSocket, "Multithreaded Server");//Class does client work
        clientThread = new Thread(client);          // Make a thread for each client
        clientThread.start();                       // start thread

        threadHandler.setUp(client, clientThread);  // Set up the thread handler
        if ( once == true) {                        // make sure the threadHandler thread is only created once
            threadThread = new Thread(threadHandler);
            threadThread.start();
            once = false;
        }   
    }
    System.out.println("Server Stopped");
}

/**
 * Check if the socket is stopped
 * @return true if the socket is stopped
 */
private synchronized boolean isStopped() {
    return this.isStopped;
}

/**
 * Stop and close the socket
 */
public synchronized void stop() {
    this.isStopped = true;
    try {
        this.serverSocket.close();
    } catch (IOException e) {
        throw new RuntimeException("Error closing server", e);
    }
}

    /**
     * Open server socket
     */
    private void openServerSocket() {
        try {
            this.serverSocket = new ServerSocket(this.serverPort);
        } catch (IOException e) {
            throw new RuntimeException("Cannot open port 8888", e);
        }
    }
}
import java.io.IOException;
导入java.net.InetAddress;
导入java.net.ServerSocket;
导入java.net.Socket;
导入java.net.SocketTimeoutException;
导入java.util.ArrayList;
导入java.util.Hashtable;
公共类多线程服务器实现可运行{
受保护的int-serverPort=8888;
受保护的ServerSocket ServerSocket=null;
受保护布尔值=false;
受保护线程runningThread=null;
受保护线程clientThread=null;
受保护线程=null;
私有哈希表用户=新哈希表();
private ArrayList ClientThreads=new ArrayList();
private WorkerRunnable client=null;
私有ThreadHandler ThreadHandler=null;
私人int声音_max=0;
private boolean once=true;
公共多线程服务器(int端口){
this.serverPort=端口;
}
公开募捐{
已同步(此){
this.runningThread=Thread.currentThread();
}
openServerSocket();
threadHandler=新的threadHandler();
而(!isStopped()){
套接字clientSocket=null;
试一试{
System.out.println(InetAddress.getLocalHost());
clientSocket=this.serverSocket.accept();//连接到客户端
}捕获(SocketTimeoutException e){
}捕获(IOE异常){
if(isStopped()){
System.out.println(“服务器停止”);
返回;
}
抛出新的运行时异常(“错误接受客户端连接”,e);
}
client=newworkerrunnable(clientSocket,“多线程服务器”);//类执行客户端工作
clientThread=新线程(客户端);//为每个客户端创建一个线程
clientThread.start();//开始线程
setUp(client,clientThread);//设置线程处理程序
如果(once==true){//请确保threadHandler线程只创建一次
threadThread=新线程(threadHandler);
threadThread.start();
一次=假;
}   
}
System.out.println(“服务器停止”);
}
/**
*检查插座是否已停止
*@如果套接字停止,则返回true
*/
私有同步布尔值(){
把这个还给我;
}
/**
*停止并关闭插座
*/
公共同步无效停止(){
this.isStopped=true;
试一试{
这个.serverSocket.close();
}捕获(IOE异常){
抛出新的运行时异常(“关闭服务器时出错”,e);
}
}
/**
*开放服务器套接字
*/
私有void openServerSocket(){
试一试{
this.serverSocket=新的serverSocket(this.serverPort);
}捕获(IOE异常){
抛出新的运行时异常(“无法打开端口8888”,e);
}
}
}
这是Worker类,用于处理来自客户端的数据:

import gnu.io.NoSuchPortException;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;

public class WorkerRunnable implements Runnable {

    protected Socket clientSocket   = null;
    protected String serverText     = null;
    private BufferedReader inFromClient;
    private DataOutputStream outToClient;
    private int[] currentPos = new int[6];
    private boolean connected = false;
    static TwoWaySerialComm serialCom = null;
    static MultiServoState mState;
    static int sound_average;
    int[] degrees = new int[7];
    int count = 0;

    public WorkerRunnable(Socket clientSocket, String serverText) {
        this.clientSocket = clientSocket;
        this.serverText = serverText;
        initCurrentPos();
        if (serialCom == null) {
             serialCom = new TwoWaySerialComm();
        }
        try {
            if (!serialCom.isConnected("COM5")) {
                try {
                    serialCom.connect("COM5");
                } catch (Exception e) {
                // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                mState = new MultiServoState(serialCom);
            }
        } catch (NoSuchPortException e) {
        // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public void run() {
        try {
            work();
        } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        }
    }

    public void work() throws InterruptedException {
        try {
            InputStream input = clientSocket.getInputStream();
            OutputStream output = clientSocket.getOutputStream();
            inFromClient = new BufferedReader(new InputStreamReader(input));
            outToClient = new DataOutputStream(output);
            long time = System.currentTimeMillis();
            updateData();
            String message = null;
            long endTime = System.currentTimeMillis() + 2000;
            while ((message = (String) inFromClient.readLine()) != null) {

                System.out.println("Message Received: " + message);
                parse(message);

                sound_average = degrees[6];
                //
                // Send the positional data to the robot
                //
                mState.runServo(degrees[0], degrees[1], degrees[2],
                    degrees[3], degrees[4], degrees[5]);


                //
                // Send a response information to the client application
                //
                currentPos[0] = mState.getCurrentPos(0);
                currentPos[1] = mState.getCurrentPos(1);
                currentPos[2] = mState.getCurrentPos(2);
                currentPos[3] = mState.getCurrentPos(3);
                currentPos[4] = mState.getCurrentPos(4);
                try {
                    updateData();
                } catch (IOException e) {
                // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            System.out.println("Request processed: " + time);
        } catch (IOException e) {
            // report exception somewhere
            e.printStackTrace();
        } 
    }

          /**
          * Initiate the robot's starting position.
          */
          public void initCurrentPos()
          {
              currentPos[0] = 100;
    currentPos[1] = 100;
    currentPos[2] = 100;
    currentPos[3] = 100;
    currentPos[4] = 100;
    currentPos[5] = 0;
          }

    /**
    * Send the data to the client
    * 
    * @throws IOException
    */
    public void updateData() throws IOException {
    String sentence = Integer.toString(currentPos[0]) + ", " + 
                      Integer.toString(currentPos[1]) + ", " +
                      Integer.toString(currentPos[2]) + ", " + 
                      Integer.toString(currentPos[3]) + ", " + 
                      Integer.toString(currentPos[4]) + "." + "\n";
        outToClient.flush();
        outToClient.writeBytes(sentence);
    }

    /**
     * Get the clients sound average
     * @param message
     */
    public int getSoundAverage() {
        return sound_average;
    }

    public void parse(String message) {
        if (message != null) {
            char c;
            StringBuilder sb = new StringBuilder(4);
            int j = 0;
            boolean help = false;

            for (int i = 0; i < message.length(); i++) {
                c = message.charAt(i);
                if (Character.isDigit(c)) {
                    sb.append(c);
                    help = true;
                }
                if (!Character.isDigit(c) && help == true) {
                    degrees[j] = Integer.parseInt(sb.toString());
                    j++;
                    help = false;
                    sb.delete(0, sb.length());
                }
            }
        }
        System.out.println("Waiting for client message...");
    }

    /**
     * Close all connections
     */
    public void close() {
        if (connected) {
            synchronized (this) {
                connected = false;
            }
            if (outToClient != null) {
                try {
                    outToClient.close();
                    synchronized (this) {
                        outToClient = null;
                    }
                } catch (IOException e) {
                    // there is nothing we can do: ignore it
                }
            }

            if (inFromClient != null) {
                try {
                    inFromClient.close();
                    synchronized (this) {
                        inFromClient = null;
                    }
                } catch (IOException e) {
                    // there is nothing we can do: ignore it
                }
            }

            if (clientSocket != null) {
                try {
                    clientSocket.close();
                    synchronized (this) {
                        clientSocket = null;
                    }
                } catch (IOException e) {
                    // there is nothing we can do: ignore it
                }
            }
        }
    }

    public void returnThread() {
        return;
    }
}
导入gnu.io.NoSuchPortException;
导入java.io.BufferedReader;
导入java.io.DataOutputStream;
导入java.io.IOException;
导入java.io.InputStream;
导入java.io.InputStreamReader;
导入java.io.OutputStream;
导入java.net.Socket;
公共类WorkerRunnable实现可运行{
受保护的套接字clientSocket=null;
受保护的字符串serverText=null;
私有缓冲读写器客户端;
私有数据输出流输出到客户端;
private int[]currentPos=新int[6];
私有布尔连接=假;
静态双向串行通信串行通信=空;
静态多伺服状态;
静态int声音_平均值;
整数[]度=新整数[7];
整数计数=0;
public WorkerRunnable(套接字客户端套接字,字符串服务器文本){
this.clientSocket=clientSocket;
this.serverText=serverText;
initCurrentPos();
if(serialCom==null){
serialCom=新的双向串行通信();
}
试一试{
如果(!serialCom.isConnected(“COM5”)){
试一试{
serialCom.connect(“COM5”);
}捕获(例外e){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
mState=新的多服务器(串行COM);
}
}捕获(无此端口例外){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
}
公开募捐{
试一试{
工作();
}捕捉(中断异常e){
//TODO自动生成的捕捉块
}
}
public void work()引发InterruptedException{
试一试{
InputStream输入=clientSocket.getInputStream();
OutputStream output=clientSocke
import java.net.ServerSocket;
import java.util.ArrayList;
import java.util.Hashtable;

import com.research.aserver.WorkerRunnable;


public class ThreadHandler implements Runnable {

    protected boolean   isStopped       = false;
    protected Thread        runningThread   = null;
    protected Thread        clientThread    = null;
    private Hashtable<Long, WorkerRunnable> Users = new Hashtable<Long, WorkerRunnable>();
    private ArrayList<Thread> ClientThreads = new ArrayList<Thread>();
    private WorkerRunnable  client      = null;
    private int     sound_max       = 0;
    private int     index       = 0;

    public ThreadHandler() {
    }

    public void setUp(WorkerRunnable client, Thread clientThread) {
        this.client = client;
        this.clientThread = clientThread;
        Users.put(clientThread.getId(), this.client);   // Place clients in a list with its thread ID as key
        ClientThreads.add(this.clientThread);           // List of client threads
    }

    @Override
    public void run() {
        long endTime = System.currentTimeMillis() + 2000;       // Help variable to check every 2 sec
        while (!Users.isEmpty() && !ClientThreads.isEmpty()) {

            for (int i = 0; i < ClientThreads.size(); i++) {    // Remove clients and threads if no longer active
                if (!ClientThreads.get(i).isAlive()) {
                    Users.remove(ClientThreads.get(i).getId());
                    ClientThreads.get(i).interrupt();
                    ClientThreads.remove(i);
                }
            }
            if(System.currentTimeMillis() >= endTime) { // Do work every 2 sec
                for (int i = 0; i < ClientThreads.size(); i++) {    // Get the client with the loudest sound
                    if (sound_max < Users.get(ClientThreads.get(i).getId()).getSoundAverage()) {
                        sound_max = Users.get(ClientThreads.get(i).getId()).getSoundAverage();
                        index = i;
                    }
                }

                for (int i = 0; i < ClientThreads.size(); i++) {    // yield all threads that are not the loudest
                    if (Users.get(ClientThreads.get(index).getId()) != Users.get(ClientThreads.get(i).getId())){
                        ClientThreads.get(i).yield();
                        index = 0;
                    }
                }
                endTime = System.currentTimeMillis() + 2000;                        // update time
            }
            sound_max = 0;
        }
    }
}