Java 套接字接受和多线程
我有这个问题,我不知道如何解决,我处于精神错乱的边缘。编程,嗯/ 无论如何,我有一个服务器,它有一个线程向用户发送它需要的所有信息(需要经常运行),还有一个线程等待新的服务器连接。我的问题是一旦调用了Java 套接字接受和多线程,java,multithreading,sockets,Java,Multithreading,Sockets,我有这个问题,我不知道如何解决,我处于精神错乱的边缘。编程,嗯/ 无论如何,我有一个服务器,它有一个线程向用户发送它需要的所有信息(需要经常运行),还有一个线程等待新的服务器连接。我的问题是一旦调用了socket.accept(),另一个线程就不会执行 因此,用代码来解释: class Thread1 extends Thread { public void run() { while(true) { s=socket.accept(); } }
socket.accept()
,另一个线程就不会执行
因此,用代码来解释:
class Thread1 extends Thread {
public void run() {
while(true)
{
s=socket.accept();
}
}
class Thread2 extends Thread {
public void run() {
//do stuff
System.out.println("spam");
}
}
public static void main(String[] args)
{
Thread1 t1 = new Thread1();
t1.start();
t1.Thread2 t2 = t1.new Thread2();
t2.start();
}
}
假设所有其他必需的成员变量都存在,没有编译错误,并且连接功能工作正常。只有“Thread2”只执行一次
所以我的问题是,我如何解决这个问题
提前感谢,
蒂姆。一些建议
- 永远不要延伸一条线,因为这是一个很好的迷惑自己的方法。除非你真的喜欢混乱,否则千万不要把一个线程嵌套在另一个线程中
- 如果要为每个套接字运行一个线程,则为循环中的每个套接字创建一个新线程
- 永远不要延伸一条线,因为这是一个很好的迷惑自己的方法。除非你真的喜欢混乱,否则千万不要把一个线程嵌套在另一个线程中
- 如果要为每个套接字运行一个线程,则为循环中的每个套接字创建一个新线程
更好的解决方案是使用线程池。e、 g.执行器服务,但我会先让它工作。我想你对线程有一个基本的误解。让我们看看能不能弄清楚 线程只是另一个执行管道。把它们想象成带有特定指令集的任务。任务完成后,线程返回。这主意很简单,对吧 在您的示例中,
Thread1
有一个无止境的循环,它可以无限期地运行并无限期地接受客户机
但是,Thread2
只是输出一些文本并返回。没有什么能告诉它“继续旋转”
在您的main()
中,即使Thread2
是Thread1
的一个内部类(我可以补充一下,这是一种糟糕的开始形式),它实际上并不强制线程继续运行
您可能希望向服务器类中添加一个包含新套接字的类,并使Thread2
循环并检查条目
进一步阅读
首先,请看一看。它的构造函数采用了一个Runnable
,因此在处理线程时,这就是您应该实现的全部内容(即类Foo实现Runnable
,然后是新线程(new Foo())
)
如果您喜欢套接字,那么您可能会从一些关于套接字服务器体系结构甚至协议设计的内容中获益。我认为您对线程有一个基本的误解。让我们看看能不能弄清楚 线程只是另一个执行管道。把它们想象成带有特定指令集的任务。任务完成后,线程返回。这主意很简单,对吧 在您的示例中,
Thread1
有一个无止境的循环,它可以无限期地运行并无限期地接受客户机
但是,Thread2
只是输出一些文本并返回。没有什么能告诉它“继续旋转”
在您的main()
中,即使Thread2
是Thread1
的一个内部类(我可以补充一下,这是一种糟糕的开始形式),它实际上并不强制线程继续运行
您可能希望向服务器类中添加一个包含新套接字的类,并使Thread2
循环并检查条目
进一步阅读
首先,请看一看。它的构造函数采用了一个Runnable
,因此在处理线程时,这就是您应该实现的全部内容(即类Foo实现Runnable
,然后是新线程(new Foo())
)
如果您喜欢套接字,那么您可能会从一些套接字服务器体系结构甚至协议设计方面受益。谢谢您的建议,我现在将在它失控之前更改我的实现:d您的回答让我意识到,我在第二个线程中需要一个while循环或计时器,否则它只执行一次-我是线程n00b:p@Timmy正如Peter正确建议的,使用Executor服务。ScheduledExecutor服务有一些很好的方法,称为“scheduleWithFixedDelay”和“SchedulePeriodic”(或类似的方法)。您可以猜到这比使用计时器要容易得多。
ExecutorService
在使用套接字时几乎毫无意义,因为Socket
操作块(通常)。如果您希望在套接字连接之间回收线程,那么他的第二个线程(与接受的套接字一起工作)将是ExecutorService
@Qix的唯一用例,您想要一个池。@PeterLawrey+1,但我认为这场讨论很快就会演变为争论是每个套接字使用阻塞线程还是使用非阻塞选择器和工作线程更好。。。OPs的问题得到了回答,现在讨论的细节远远超出了它的范围。谢谢你的建议,在它失控之前,我现在就改变我的实施方式:D你的回答让我意识到,我在第二个线程中需要一个while循环或计时器,否则它只执行一次-我是线程n00b:p@Timmy正如Peter正确建议的,使用Executor服务。ScheduledExecutor服务有一些很好的方法,称为“scheduleWithFixedDelay”和“SchedulePeriodic”(或类似的方法)。你可以猜到这比使用计时器要容易得多。ExecutorService
在使用套接字时几乎毫无意义,因为class SocketAcceptor implements Runnable {
public void run() {
while(true) {
Socket s=socket.accept();
SocketHandler sh = new SocketHandler(s);
new Thread(sh).start();
}
}
}
class SocketHandler implements Runnable {
final Socket s;
SocketHandler(Socket s) { this.s = s; }
public void run() {
System.out.println("New connection " + s);
s.close();
}