[英]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;
必须是静态的? 这意味着所有线程共享您的输出流!
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.