使用套接字编程的简单聊天应用程序出现 IllegalThreadStateException 错误,代码如下
IllegalThreadStateException Error on Simple Chat Application using Socket Programmin, Code bellow
客户代码:
import java.io.BufferedReader;
import java.io.IOError;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.*;
import java.util.Scanner;
import javax.swing.*;
import java.io.*;
public class messages_client
{
static BufferedReader in;
static Scanner sc;
static PrintWriter out;
public static void main(String args[])
{
try{
JFrame frame=new JFrame();
Socket client=new Socket("localhost",59001);
in=new BufferedReader(new InputStreamReader(client.getInputStream()));
out=new PrintWriter(client.getOutputStream(),true);
sc=new Scanner(System.in);
boolean running=false;
String input=in.readLine();
System.out.println(input);
String name=sc.next();
out.println(name);
running=true;
Thread send=new Thread(new send());
Thread recieve=new Thread(new recieve());
if(running == true)
{
while(true)
{
send.start();
recieve.start();
}
}
} catch(IOException e){}
}
public static class send implements Runnable
{
@Override
public void run()
{
String message=sc.nextLine();
out.println(message);
}
}
public static class recieve implements Runnable
{
@Override
public void run()
{
try {
String input=in.readLine();
System.out.println(input);
} catch (IOException e) {
}
}
}
}
服务器代码:
import java.io.*;
import java.net.*;
import java.util.*;
import java.util.concurrent.Executors;
public class messages_server
{
private static ServerSocket server;
private static Set<PrintWriter> printwriters=new HashSet<>();
public static void main(String args[])
{
try{
server=new ServerSocket(59001);
var pool=Executors.newFixedThreadPool(5);
System.out.println("Server is running");
while(true)
{
pool.execute(new ClientHandler(server.accept()));
}
} catch(IOException e)
{
} finally
{
try{
server.close();
} catch(IOException e){}
}
}
private static class ClientHandler implements Runnable
{
private Socket client;
private static PrintWriter out;
private static BufferedReader in;
private static String message;
private static String name;
ClientHandler(Socket client)
{
this.client=client;
}
@Override
public void run()
{
try{
out=new PrintWriter(client.getOutputStream(),true);
in=new BufferedReader(new InputStreamReader(client.getInputStream()));
send("Name: ");
name=in.readLine();
System.out.println(name);
out.println("1");
broadcast(name+" has joined the chat");
while(true)
{
message=in.readLine();
broadcast(name+":"+message);
}
} catch(IOException e){}finally
{
if(in != null)
{
printwriters.remove(out);
broadcast(name+" has left the chat");
}
try{
client.close();
}catch(IOException e){}
}
}
public void broadcast(String message)
{
for(PrintWriter printwriter:printwriters)
{
printwriter.println(message);
}
}
public void send(String message)
{
out.println(message);
}
}
}
我创建了这个简单的聊天应用程序,其中多个用户可以加入一个公共 chat.The 服务器为每个客户端创建不同的线程并持续接收和广播 data.The 客户端有两个线程:“发送" "recieve" 连续发送和接收数据。
服务器工作正常,但是当我 运行 客户端在输入我的名字后显示 IllegalThreadStateException
。
请帮助和建议我是否也可以改进此代码。
我认为您对 Thread
的 start()
方法的作用感到困惑。
在您的代码中:
Thread send = new Thread(new send());
Thread recieve = new Thread(new recieve());
您只创建了一个线程 (send
) 用于发送,并且只创建了一个线程 (recieve
- 请注意您打错了字,它是“接收”。英语很奇怪) 用于接收。
你然后:
while(true)
{
send.start();
recieve.start();
}
重复(while 循环)在这些单线程上调用 .start()
。
它不是这样工作的:你只能启动一个 Thread 对象一次,永远。如果你第二次调用.start()
,你会得到IllegalThreadStateException
,因为状态是'STARTED',你不能在这样的线程上调用.start()
。
你的意图不太清楚。您是否打算不断启动线程?然后你必须每次都创建一个新的线程对象然后启动它,即将 Thread send = ...;
代码移动到 while 循环中。但是,我无法想象你想要这样:如果你把它放在 while(true)
中,系统将创建无限数量的线程,启动它们,并且,如果你尝试这样做,自然会非常非常快地崩溃.
如果您的意图只是阻止一个发送线程和一个接收线程继续 运行 - 则无需重复调用 .start()
或从 [=23= 执行任何其他操作] 方法 - 您的接收和发送 运行nables 已经 有循环(它们都有自己的 while(true)
循环)。
如果您打算重新启动任何以某种方式自行停止的线程,'just in case' - 这不是它的工作原理。一旦线程结束,您将无法再次启动它 - 您必须创建一个新线程。正如之前所讨论的,只创建无限数量的线程只会导致 swift 崩溃。您可以询问线程是否不再 运行ning,然后创建一个新线程并启动新线程,但您不应该进行防御性编程。
让我澄清一下,因为术语 'defensive programming' 已经过载:您不应该编写代码来处理不理解的情况。在这种情况下,情况是:“我不太清楚如何,但让我们想象一下发送线程以某种方式停止了。如果发生这种情况,我想重新启动它”。这种防御性编程不好的原因是:根据定义,你并不真正知道发生了什么(毕竟,你不知道某些状态是如何发生的,因此你很可能错过了对什么是当你不可能的情况确实发生时继续进行),所以你做正确的事情('just restart it' 是 'huh, weird, that thread stopped and I do not understand why' 的正确答案)的可能性很低。
最有可能的是,您无法理解的情况实际上可能永远不会发生,因此您编写了一堆永远不会 运行 的代码。这导致了防御性编程的最大问题:代码不可测试, 和 很少(通常从不)运行,这意味着其中的任何错误都完全没有被注意到。所以你现在有无用的代码,即使它变得有用,也根本不起作用。
在这种不可能的情况下,FAR 最好只是 hard-crash 例外。至少到那时,如果确实发生了,您就可以带头进行调查。只有理解了,才能写出处理这种情况的代码。
客户代码:
import java.io.BufferedReader;
import java.io.IOError;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.*;
import java.util.Scanner;
import javax.swing.*;
import java.io.*;
public class messages_client
{
static BufferedReader in;
static Scanner sc;
static PrintWriter out;
public static void main(String args[])
{
try{
JFrame frame=new JFrame();
Socket client=new Socket("localhost",59001);
in=new BufferedReader(new InputStreamReader(client.getInputStream()));
out=new PrintWriter(client.getOutputStream(),true);
sc=new Scanner(System.in);
boolean running=false;
String input=in.readLine();
System.out.println(input);
String name=sc.next();
out.println(name);
running=true;
Thread send=new Thread(new send());
Thread recieve=new Thread(new recieve());
if(running == true)
{
while(true)
{
send.start();
recieve.start();
}
}
} catch(IOException e){}
}
public static class send implements Runnable
{
@Override
public void run()
{
String message=sc.nextLine();
out.println(message);
}
}
public static class recieve implements Runnable
{
@Override
public void run()
{
try {
String input=in.readLine();
System.out.println(input);
} catch (IOException e) {
}
}
}
}
服务器代码:
import java.io.*;
import java.net.*;
import java.util.*;
import java.util.concurrent.Executors;
public class messages_server
{
private static ServerSocket server;
private static Set<PrintWriter> printwriters=new HashSet<>();
public static void main(String args[])
{
try{
server=new ServerSocket(59001);
var pool=Executors.newFixedThreadPool(5);
System.out.println("Server is running");
while(true)
{
pool.execute(new ClientHandler(server.accept()));
}
} catch(IOException e)
{
} finally
{
try{
server.close();
} catch(IOException e){}
}
}
private static class ClientHandler implements Runnable
{
private Socket client;
private static PrintWriter out;
private static BufferedReader in;
private static String message;
private static String name;
ClientHandler(Socket client)
{
this.client=client;
}
@Override
public void run()
{
try{
out=new PrintWriter(client.getOutputStream(),true);
in=new BufferedReader(new InputStreamReader(client.getInputStream()));
send("Name: ");
name=in.readLine();
System.out.println(name);
out.println("1");
broadcast(name+" has joined the chat");
while(true)
{
message=in.readLine();
broadcast(name+":"+message);
}
} catch(IOException e){}finally
{
if(in != null)
{
printwriters.remove(out);
broadcast(name+" has left the chat");
}
try{
client.close();
}catch(IOException e){}
}
}
public void broadcast(String message)
{
for(PrintWriter printwriter:printwriters)
{
printwriter.println(message);
}
}
public void send(String message)
{
out.println(message);
}
}
}
我创建了这个简单的聊天应用程序,其中多个用户可以加入一个公共 chat.The 服务器为每个客户端创建不同的线程并持续接收和广播 data.The 客户端有两个线程:“发送" "recieve" 连续发送和接收数据。
服务器工作正常,但是当我 运行 客户端在输入我的名字后显示 IllegalThreadStateException
。
请帮助和建议我是否也可以改进此代码。
我认为您对 Thread
的 start()
方法的作用感到困惑。
在您的代码中:
Thread send = new Thread(new send()); Thread recieve = new Thread(new recieve());
您只创建了一个线程 (send
) 用于发送,并且只创建了一个线程 (recieve
- 请注意您打错了字,它是“接收”。英语很奇怪) 用于接收。
你然后:
while(true) { send.start(); recieve.start(); }
重复(while 循环)在这些单线程上调用 .start()
。
它不是这样工作的:你只能启动一个 Thread 对象一次,永远。如果你第二次调用.start()
,你会得到IllegalThreadStateException
,因为状态是'STARTED',你不能在这样的线程上调用.start()
。
你的意图不太清楚。您是否打算不断启动线程?然后你必须每次都创建一个新的线程对象然后启动它,即将 Thread send = ...;
代码移动到 while 循环中。但是,我无法想象你想要这样:如果你把它放在 while(true)
中,系统将创建无限数量的线程,启动它们,并且,如果你尝试这样做,自然会非常非常快地崩溃.
如果您的意图只是阻止一个发送线程和一个接收线程继续 运行 - 则无需重复调用 .start()
或从 [=23= 执行任何其他操作] 方法 - 您的接收和发送 运行nables 已经 有循环(它们都有自己的 while(true)
循环)。
如果您打算重新启动任何以某种方式自行停止的线程,'just in case' - 这不是它的工作原理。一旦线程结束,您将无法再次启动它 - 您必须创建一个新线程。正如之前所讨论的,只创建无限数量的线程只会导致 swift 崩溃。您可以询问线程是否不再 运行ning,然后创建一个新线程并启动新线程,但您不应该进行防御性编程。
让我澄清一下,因为术语 'defensive programming' 已经过载:您不应该编写代码来处理不理解的情况。在这种情况下,情况是:“我不太清楚如何,但让我们想象一下发送线程以某种方式停止了。如果发生这种情况,我想重新启动它”。这种防御性编程不好的原因是:根据定义,你并不真正知道发生了什么(毕竟,你不知道某些状态是如何发生的,因此你很可能错过了对什么是当你不可能的情况确实发生时继续进行),所以你做正确的事情('just restart it' 是 'huh, weird, that thread stopped and I do not understand why' 的正确答案)的可能性很低。
最有可能的是,您无法理解的情况实际上可能永远不会发生,因此您编写了一堆永远不会 运行 的代码。这导致了防御性编程的最大问题:代码不可测试, 和 很少(通常从不)运行,这意味着其中的任何错误都完全没有被注意到。所以你现在有无用的代码,即使它变得有用,也根本不起作用。
在这种不可能的情况下,FAR 最好只是 hard-crash 例外。至少到那时,如果确实发生了,您就可以带头进行调查。只有理解了,才能写出处理这种情况的代码。