繁体   English   中英

MultiThreading,Java Server / Client Project

[英]MultiThreading, Java Server/Client Project

您好我正在使用Java中的服务器/客户端程序,其中客户端连接到服务器并向服务器发送数字,然后服务器将此数字添加到全局变量并返回全局变量。 我遇到的问题是当我有多个客户端时,一个客户端不工作而另一个客户端不工作,后来创建的客户端工作。 我为每个客户创建了单独的线程,并在一定程度上工作。

这是我的服务器类的片段,用于创建新线程

public static Integer globalSum = 0;

public static void main(String[] args) throws IOException
{

    ServerSocket server = new ServerSocket(8888);
    Socket s;

    System.out.println("Server running. Waiting for a client to connect...");

    while(true) {

        s = server.accept();
        ThreadHandler th=new ThreadHandler(s);
        Thread t=new Thread(th);
        t.start();
        System.out.println("Client is now connected");

    }
}

这是我的客户端类

public class Client2 {

    public static void main(String[] args) throws IOException {
        Socket s = new Socket("localhost", 8888);
        InputStream instream = s.getInputStream();
        OutputStream outstream = s.getOutputStream();
        Scanner in = new Scanner(instream);
        Scanner input= new Scanner(System.in);
        PrintWriter out = new PrintWriter(outstream);

        for(int i=0;i<5;i++){
            System.out.println("Please enter a value "+(i+1));
            String response=input.nextLine();
            String request="SUBMIT"+" "+response+"\n";
            out.print(request);
            out.flush();
            System.out.println(in.nextLine());
        }

        out.print("QUIT\n");
        out.flush();

        s.close();
    }

}

这是我的ThreadHandler类

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Scanner;

public class ThreadHandler implements Runnable {

    private Socket s;
    private Scanner in;
    private static PrintWriter out;
    ServerMultipleClients serverInstance;

    public ThreadHandler(Socket s)
    {
        //this.serverInstance=serverInstance;
        this.s=s;

    }

    public void run() {
        try {
            try {

                in = new Scanner(s.getInputStream());
                out = new PrintWriter(s.getOutputStream());

                doService(); // the actual service

            } finally {
                s.close();
            }

        } catch (IOException e) {
            System.err.println(e);
        }
        return;
    }


    public void doService() throws IOException{

        String request;

        while(true){

            request=in.next();
            String arrayString[] = request.split("\\s+") ;
            if(request.equals("SUBMIT")){
                String value2=in.next();
                handle(value2);
            }
            else if (request.equals("QUIT")){
                break;
            }
            else if(!request.equals("SUBMIT")||!request.equals("QUIT")){
                System.out.println("ERROR in input");
                break;
            }

        }

    }


    public void handle(String value1){

        if(isInt(value1)==true){

            int valueInt=Integer.parseInt(value1);

            synchronized(serverInstance.globalSum) {

                if((valueInt+serverInstance.globalSum)<Integer.MAX_VALUE){
                    ServerMultipleClients.globalSum=ServerMultipleClients.globalSum+valueInt;
                    out.println("OK");
                    out.flush();
                    System.out.println("New Value for Global Sum is: "+ServerMultipleClients.globalSum);
                }
                else if((valueInt+ServerMultipleClients.globalSum)>=Integer.MAX_VALUE){
                    out.println("ERROR");
                    System.out.println("Global Sum is unchanged, its value is: "+ServerMultipleClients.globalSum);
                }
                else{
                    out.println("ERROR");
                    System.out.println("Global Sum is unchanged, its value is: "+ServerMultipleClients.globalSum);
                }

            }
        }
    }

    public boolean isInt( String input ) {
        try {
            Integer.parseInt( input );
            return true;
        }
        catch( Exception e ) {
            return false;
        }
    }

}

问题是,当我运行它时,它适用于稍后运行到前一个客户端的每个客户端,返回到前一个客户端意味着该客户端崩溃。

你确定这件事:

private static PrintWriter out;

必须是静态的? 这意味着所有线程共享您的输出流!

  1. 你有什么样的错误?
  2. 为什么选择PrintWriter out; 是静态的?

无论如何,我会替换

public static Integer globalSum = 0;

AtomicInteger globalSum = new AtomicInteger();

并取一次值:

myValueAtThisTime =  globalSum.addAndGet(valueInt);

也许这不是你问题的答案,但我看到的东西看起来像是一个很大(而且很常见)的错误。

我没有看到ServerInstance.globalSum的声明,但我猜,它是一个整数。 对?

每次分配时,您都在创建一个新对象:

ServerMultipleClients.globalSum=ServerMultipleClients.globalSum+valueInt;

这意味着,当您的代码在ServerMultipleClients.globalSum同步时,每个线程可能正在同一个不同的Integer对象上进行同步。 这意味着,任何数量的线程都可以同时进入“同步”块。

每当你编写synchronized(foo) ,你可能希望foo成为最终变量。 例如,

private final Object foo = new Object();

这样,您可以绝对确定不同的线程不会在不同的实例上同步。

还要注意! 如果使用synchronized(foo)来保护静态数据,那么foo本身必须是静态的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM