Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使服务器队列成为java的最简单、最好的方法_Java_Sockets - Fatal编程技术网

使服务器队列成为java的最简单、最好的方法

使服务器队列成为java的最简单、最好的方法,java,sockets,Java,Sockets,我现在有一个服务器,它为每个连接的用户创建一个新的线程,但是在大约6个人在服务器上超过15分钟后,它往往会失败,并给我java堆内存不足错误。我有一个线程,每30秒检查一次mysql数据库,查看当前登录的用户是否有任何新消息。实现服务器队列最简单的方法是什么 这是我的服务器的主要方法: public class Server { public static int MaxUsers = 1000; //public static PrintStream[] sessions =

我现在有一个服务器,它为每个连接的用户创建一个新的线程,但是在大约6个人在服务器上超过15分钟后,它往往会失败,并给我java堆内存不足错误。我有一个线程,每30秒检查一次mysql数据库,查看当前登录的用户是否有任何新消息。实现服务器队列最简单的方法是什么

这是我的服务器的主要方法:

public class Server {

    public static int MaxUsers = 1000;
    //public static PrintStream[] sessions = new PrintStream[MaxUsers];
    public static ObjectOutputStream[] sessions = new ObjectOutputStream[MaxUsers];
    public static ObjectInputStream[] ois = new ObjectInputStream[MaxUsers];
    private static int port = 6283;
   public static Connection conn;
       static Toolkit toolkit;
    static Timer timer;

    public static void main(String[] args) {
        try {
            conn = (Connection) Mysql.getConnection();
        } catch (Exception ex) {
            Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
        }
        System.out.println("****************************************************");
        System.out.println("*                                                  *");
        System.out.println("*                    Cloud Server                  *");
        System.out.println("*                       ©2010                      *");
        System.out.println("*                                                  *");
        System.out.println("*                   Luke Houlahan                  *");
        System.out.println("*                                                  *");
        System.out.println("* Server Online                                    *");
        System.out.println("* Listening On Port " + port + "                           *");
        System.out.println("*                                                  *");
        System.out.println("****************************************************");
        System.out.println("");
        mailChecker();
        try {
            int i;
            ServerSocket s = new ServerSocket(port);
            for (i = 0; i < MaxUsers; ++i) {
                sessions[i] = null;
            }
            while (true) {
                try {
                    Socket incoming = s.accept();                    
                    boolean found = false;
                    int numusers = 0;
                    int usernum = -1;
                    synchronized (sessions) {
                        for (i = 0; i < MaxUsers; ++i) {
                            if (sessions[i] == null) {
                                if (!found) {
                                    sessions[i] = new ObjectOutputStream(incoming.getOutputStream());
                                    ois[i]= new ObjectInputStream(incoming.getInputStream());
                                    new SocketHandler(incoming, i).start();
                                    found = true;
                                    usernum = i;
                                }
                            } else {
                                numusers++;
                            }
                        }
                        if (!found) {
                            ObjectOutputStream temp = new ObjectOutputStream(incoming.getOutputStream());
                            Person tempperson = new Person();
                            tempperson.setFlagField(100);
                            temp.writeObject(tempperson);
                            temp.flush();
                            temp = null;
                            tempperson = null;
                            incoming.close();
                        } else {
                        }
                    }
                } catch (IOException ex) {
                    System.out.println(1);
                    Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        } catch (IOException ex) {
            System.out.println(2);
            Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
        public static void mailChecker() {
        toolkit = Toolkit.getDefaultToolkit();
        timer = new Timer();
        timer.schedule(new mailCheck(), 0, 10 * 1000);
    }
}
公共类服务器{
公共静态int MaxUsers=1000;
//公共静态PrintStream[]会话=新的PrintStream[MaxUsers];
公共静态ObjectOutputStream[]会话=新ObjectOutputStream[MaxUsers];
公共静态ObjectInputStream[]ois=新ObjectInputStream[MaxUsers];
专用静态int端口=6283;
公共静态连接;
静态工具包;
静态定时器;
公共静态void main(字符串[]args){
试一试{
conn=(连接)Mysql.getConnection();
}捕获(例外情况除外){
Logger.getLogger(Server.class.getName()).log(Level.SEVERE,null,ex);
}
System.out.println(“*******************************************************************************”);
System.out.println(“**”);
System.out.println(“*云服务器*”);
System.out.println(“*©2010*”);
System.out.println(“**”);
System.out.println(“*Luke Houlahan*”);
System.out.println(“**”);
System.out.println(“*服务器在线*”);
System.out.println(“*监听端口”+端口+“*”);
System.out.println(“**”);
System.out.println(“*******************************************************************************”);
System.out.println(“”);
邮件检查器();
试一试{
int i;
ServerSocket s=新的ServerSocket(端口);
对于(i=0;i
您应该查看Java NIO以构建可伸缩服务器

您似乎有内存泄漏。6条线不多。我怀疑这是因为ObjectInputStream和ObjectOutputStream缓存了所有传输的对象。这使得他们很不适合长时间的转会。您认为您正在发送一个对象,然后对其进行gc'ed,但它实际上被对象流保存在内存中

要刷新流缓存,请使用

  objectOutputStream.reset()
使用
writeObject()写入对象后

编辑: 要获得线程池,可以将
SocketHandler
传递给
Executor
,而不是启动它自己的线程。您可以创建一个执行者,如:

Executor executor = Executors.newFiexThreadPool(MaxUsers);
执行器创建为字段,或与服务器套接字处于同一级别。然后 接受连接时,请将SocketHandler添加到执行器:

executor.execute(new SocketHandler(...));
但是,如果您的客户机是长寿命的,那么这将不会有什么改进,因为与每个线程上完成的工作量相比,线程启动时间很短。池对于执行许多小任务(而不是几个大任务)最有效

关于使服务器更加健壮,一些快速提示

  • 确保启动时有足够的内存,或者至少将最大内存设置为预期1000个用户的需要
  • 使用负载测试框架(如ApacheJMeter)验证它是否可以扩展到最大用户数
  • 为数据库使用连接池,不要手工编写JDBC调用代码——使用已建立的框架