多线程是比较容易出java.lang.OutOfMemoryError 我总是关闭重起,好象真机上没有出现过。但是问题一直没有解决!

解决方案 »

  1.   

    while (buffSize!=-1) {
          new ProcessThread(this.s);
        }
    这不是死循环么,buffSize是个变量在这个循环体里面值根本不变,结果就是不停地建立新线程,然后就out of memory了
      

  2.   

    谢谢aladar(深蓝),我以前用的是while(true),想想肯定不对。我想应该是得到整个消息的大小。如果读完了就不处理了。看来这种方式也不行。能不能帮我想想办法呢。
      

  3.   

    对 aladar(深蓝) ,就是这个意思.
      

  4.   

    可以试试在 class ServerThread 里面把 bufferSize设置成static,
    然后在class ProcessThread 下面的run()方法体里面加上一句SeverThread.bufferSize=-1.
    当然,其他地方的bufferSize 都要改成SeverThread.bufferSize.
    我是个菜鸟啊。
    有什么错误请指教
      

  5.   

    在server收到一个连接请求后,建立一个线程,把socket传过去。然后在线程中看socket里是否有数据,有的话就读出socket里所有的数据,建立一个process线程并把数据作为参数,进行处理。这样就不会有死循环了。
      

  6.   

    fufeiyu112, 你的方法在多线程环境下不一定有效的,如果在新的线程开始执行前它又去判断buffersize是否为-1的话,就会多建立出一个线程了。
      

  7.   

    在server收到一个连接请求后,建立一个线程,把socket传过去。然后在线程中看socket里是否有数据,有的话就读出socket里所有的数据,建立一个process线程并把数据作为参数,进行处理。这样就不会有死循环了。
    aladar(深蓝)按照这样的处理和我第一次写的代码不是一样,还是一个线程处理一条消息?我想一个线程处理多条消息该怎么做?
      

  8.   

    不太理解你的想法。
    首先,针对一个请求连接,建立一个线程,没什么问题。然后,针对其中的内容处理时(估计你用的是异步机制),你应该有一定的协议分析机制。可是你没有!其它问题:buffSize!=-1
    你这个buffSize只读了一次,是你忘了贴代码了,还是就是这样呢?
      

  9.   

    在server收到一个连接请求后,建立一个线程,把socket传过去。然后在线程中看socket里是否有数据,有的话就读出socket里所有的数据,建立一个process线程并把数据作为参数,进行处理。这样就不会有死循环了。
    aladar(深蓝)按照这样的处理和我第一次写的代码不是一样,还是一个线程处理一条消息?我想一个线程处理多条消息该怎么做?
    =============================
    是多条消息啊,在server thread里看到有消息就读出来给新建的processThread,然后继续等下一条啊
    while(true) {
       if(有消息) {
         从stream中读出消息;
         new processThread(消息);
       } 
       this.yield(); //放弃cpu时间,不会使cpu占100%
    }偶在写例子代码,一会贴上来
      

  10.   

    hiking() 对协议的分析处理已经没有问题,我想问题就出在我的整个流程上.因为对方发过来的消息是在一个socket中,我第一次写的代码是过来一个socket连接起一个线程对消息处理。但只能处理一条消息.可是对方是一个socket连接发送过来n个消息。我没有一个线程处理n个消息的方法,所以写了后边的代码。但我知道我这种方式对不对
      

  11.   

    import java.io.*;
    import java.net.*;public class SServer {
        public static void main(String argv[]) {
            System.out.println("Server starting...");
            try {
                ServerSocket server=new ServerSocket(10000);
                while(true) {
                    Socket s = server.accept();
                    System.out.println("Accept socket");
                    new ServerThread(s).start();
                }
            } catch (IOException ioe) {
                System.out.println("Socket failed.");
            }
        }
    }class ServerThread extends Thread {
        private Socket s=null;
        
        public ServerThread(Socket s) {
            this.s=s;
        }
        
        public void run() {
            try {
                BufferedReader reader=new BufferedReader(new InputStreamReader(s.getInputStream()));
                DataOutputStream out=new DataOutputStream(s.getOutputStream());            while(!s.isClosed()) {
                    while(reader.ready()) { //如果有数据
                        String data=reader.readLine(); //读出数据
                        System.out.println("Start processing:"+data);
                        new ProcessThread(data, out).start();  //交给新的线程处理
                    }
                    this.yield();
                }
                System.out.println("Socket closed.");
            } catch (IOException ioe) {
                System.out.println("i/o error");
            }    }
    }class ProcessThread extends Thread {
        private String data=null;
        private DataOutputStream out=null;
        public ProcessThread(String data, DataOutputStream out) {
            this.data=data;
            this.out=out;
        }
        public void run() {
            try {
                this.sleep(1000); //模拟处理所花的时间
                out.writeBytes("Echo from Server:"+data.toUpperCase()+"\r\n");
            } catch (Exception e) {
                System.out.println("process failed.");
            }    }
    }只是一个小模型,我已经测试过了,可以接收多个socket并处理一个socket的多个消息
      

  12.   

    往深说一下while(!s.isClosed()) {
          while(reader.ready()) { //如果有数据
          String data=reader.readLine(); //读出数据这里的readLine是针对客户端发送了 \r,\n这些字符,如果客户端分几次发送一个信息体,使用\r \n作为每次发送的结尾,则readLine一次性读出来的内容就是残缺不全的。所以在一些比较重要的场合还是使用一些标志位检测,每段消息体前几个字节用来做一个标志位,接着几个字节里存储此次消息的长度,每次都是先判断标志位,如果正确,则读取指定长度,然后做自己的处理。以前给公司做的一些网络平台中,使用的就是这种比较常用的协议包头。
      

  13.   

    另外,Thread.yield(); 方法是让当前正在执行的线程暂时放弃执行权,让其他线程执行,这个方法在这里感觉似乎没什么问题.【yield是Thread的静态方法,是让当前执行的线程pause,用this来调用它没有实际意义,虽然当前能执行到yield()的是this,不过建议直接改成Thread.yield()】但实际运行的时候,这种方式CPU占用率很高,对于本例,当只有一个客户的时候,该客户产生的线程yield ,放弃执行权,还有其他哪些线程呢?main 阻塞中...
    其他JAVA虚拟机线程不考虑...
    ...yield后,可能临时降低自己的优先级,到队列中排队,以便某个其他线程能够运行,但这种方法并不提倡,通常情况下,应尽量不要依靠线程优先级来控制线程的状态。可以改用Thread.sleep(XXX); ,这种方式比较好一些。