我在我的Android应用程序中获得了服务器的线程,并且当用户决定关闭它时需要正确处理它。我选择了无阻塞的ServerSocketChannel,它接受()客户端 得到了这个
public class SocketServer extends Thread
{
private static final String LOG_TAG = "SocketServer";
private boolean isRunning = false;
private ServerSocketChannel listener = null;
public void _stop()
{
this.isRunning = false;
}
public void _start()
{
this.isRunning = true;
this.start();
}
private void free()
{
try
{
listener.close();
}
catch (IOException e)
{
//Error handle
}
listener = null;
}
public SocketServer(int port)
{
super();
try
{
listener = ServerSocketChannel.open();
listener.configureBlocking(false);
listener.socket().bind(new InetSocketAddress(port));
}
catch (IOException e)
{
//Error handle
}
}
public void run()
{
SocketChannel client = null;
while(isRunning)
{
try
{
client = listener.accept();//GC going mad
}
if(client != null)
Log.i(LOG_TAG, "ACCEPTED CLIENT");
catch (IOException e)
{
//Error handle
}
}
free();
}
我所做的就是接受新客户端 - 因为没有传入连接而获得 null ,并在服务器停止之前再次执行此操作。
ServerClient 客户端在开始时为空,如果没有可用连接,则由accept()分配给 null 。
但是Java的垃圾收集器认为什么客户端以某种方式通过accept()或者accept()以某种方式分配一些内存,GC在每个while循环之后清理。
如果注释accept()行(例如什么也不做)那么根本就没有GC,所以在accept()中完全出问题。
在我看来这是不对的。
PS 如果有某种方法可以打破阻止 ServerSocket 接受()/ 套接字读取()状态并正常退出,请告诉我
P.S。 2 写入/读取SocketChannel socket()对Socket是否安全,是否会阻塞线程?
答案 0 :(得分:1)
Java中的许多操作都在内部创建临时对象来完成他们的工作。
使用阻塞SocketServer会好得多。这样,它创建的对象仅基于每个接受的套接字而不是基于每次尝试的基础。
我建议你先为每个连接用一个线程(或两个)实现阻塞NIO。如果您发现自己的线程数存在性能问题,请尝试使用具有非阻塞NIO的Selector。