我的程序运行一段时间,就会僵死(就是进程还在,不处理任何客户端请求),求高人指点迷津!!! 我的服务程序如下: 
public class Server {     protected String SocketPort; // 监听的socket端口号 
    private int count = 0; //计数器  08.12.24 
    /** 
    * @param SocketPort--socket端口号 
    */ 
    public Server(String SocketPort) { 
        this.SocketPort = SocketPort; 
    }     // 启动线程 
    public void start() { 
        DBCall db = null; 
        try { 
            ServerSocket Server = new ServerSocket(Integer 
                    .parseInt(this.SocketPort)); 
            db = new DBCall(); 
            db.getConnection(); 
            while (true) { 
                Socket s = Server.accept(); 
                ServerThread st = new ServerThread(s, db); 
                st.start(); 
            }         } catch (Exception ex) { 
            ex.printStackTrace();         } finally { 
            if (db != null) { 
                db.closeConnection(); 
            } 
        } 
    }     // 内部线程类 
    class ServerThread extends Thread { 
        private Socket socket = null;         private DBCall db = null;//数据库连接,长连接         protected InputStream streamReader;         protected BufferedReader reader;         ServerThread(Socket s, DBCall db) { 
            this.socket = s; 
            this.db = db; 
        } 
        /* 
        * (non-Javadoc) 
        * 
        * @see java.lang.Thread#run() 
        */ 
        public void run() { 
            Object obj = new Object(); 
            synchronized (obj) { 
                while (true) { 
                    if (Counter.parse()) { 
                        Counter.add(); 
                        break; 
                    } else { 
                        try { 
                            Thread.sleep(1000); 
                        } catch (InterruptedException ex1) { 
                        } 
                        continue ; 
                    } 
                } 
            } 
            int localCount = 0; 
            SimpleDateFormat sdf = new SimpleDateFormat("", 
                    Locale.SIMPLIFIED_CHINESE); 
            sdf.applyPattern("yyyy-MM-dd HH:mm:ss"); 
            String context = ""; 
            File f = null; 
            if ("1".equals(NodeName.LOGFLAG)) { 
                f = new File(NodeName.LOGPATH); 
            } 
            //File f = new File("c:\\socketInfo.txt"); 
            try { 
                //// 08.12.24 
                if (count == 10000) { 
                    count = 0; 
                } 
                count++; 
                localCount = count; 
                FileWriter fw = null; 
                BufferedWriter bw = null; 
                if ("1".equals(NodeName.LOGFLAG)) { 
                    if (!f.exists()) { 
                        f.createNewFile(); 
                        if (!f.exists()) { 
                            System.out.println("建立socketInfo.txt文件失败!"); 
                        } 
                    } 
                    fw = new FileWriter(f, true); 
                    bw = new BufferedWriter(fw);                     Date d = new java.sql.Date(System.currentTimeMillis()); 
                    String timeStr = sdf.format(d); 
                    System.out.println("NO" + localCount + 
                                      ":go in ServerScocke=" + 
                                      timeStr);                     bw.write("\r\n"); 
                    context = "NO" + localCount + ":go in ServerScocke=" + 
                              timeStr; 
                    bw.write(context); 
                    bw.flush();                 } 
                //// 08.12.24 
                streamReader = socket.getInputStream();                 reader = new BufferedReader(new InputStreamReader(streamReader, 
                        "UTF-8"));                 String msg = ""; 
                StringBuffer msgBuffer = new StringBuffer(); 
                while ((msg = reader.readLine()) != null) { 
                    msgBuffer.append(msg); 
                }                 String phone = ParseXMLStr.parse(msgBuffer.toString(), 
                                                NodeName.node1); 
                String fmt = ParseXMLStr.parse(msgBuffer.toString(), 
                                              NodeName.node2); 
                String data = ParseXMLStr.parse(msgBuffer.toString(), 
                                                NodeName.node3);                 boolean result = false; 
                try { 
                    if (db.con == null) { 
                        db.getConnection(); 
                    } 
                    result = db.callprodure(phone, fmt, data, localCount); 
                    if (result) { 
                        System.out.println("sucessfully" + " phone:" + phone 
                                          + " fmt: " + fmt + " data: " + data); 
                    } else { 
                        System.out.println("error" + " phone:" + phone 
                                          + "  fmt: " + fmt + " data: " + data); 
                    } 
                } catch (SQLException e) { 
                    e.printStackTrace(); 
                }             } catch (IOException e) { 
                e.printStackTrace(); 
            } finally { 
                try { 
                    reader.close(); 
                } catch (IOException e) { 
                    e.printStackTrace(); 
                } 
                try { 
                    streamReader.close(); 
                } catch (IOException e) { 
                    e.printStackTrace(); 
                } 
                try { 
                    socket.close(); 
                } catch (IOException e) { 
                    e.printStackTrace(); 
                } 
            } 
            Counter.sub(); 
        } 
    } 1其中重要的Counter类如下: public class Counter { 
    public static int counter=0; 
    public static int max=new Integer(NodeName.THREADNUM).intValue(); 
    public synchronized static boolean parse(){ 
        if(Counter.counter < Counter.max){ 
            return true; 
        }else{ 
            return false; 
        } 
    } 
    public synchronized static void add(){ 
        Counter.counter += 1; 
    } 
    public synchronized static void sub(){ 
        Counter.counter-=1; 
    } 
} 是不是Counter类中的conuter变量并发引起的啊??? 
高人指点啊,事情紧急, 

解决方案 »

  1.   

    Object obj = new Object();
                synchronized (obj) {
                    while (true) {
                        if (Counter.parse()) {
                            Counter.add();
                            break;
                        } else {
                            try {
                                Thread.sleep(1000);
                            } catch (InterruptedException ex1) {
                            }
                            continue ;
                        }
                    }
                } 
    你这样做意义何在?
    每个线程都有自己的obj 作为lock......互斥效果根本达不到
      

  2.   

    另外,使用线程池就能达到你的(同时只有MAX个线程在响应)的需求使用线程池也是经常启动短期线程的推荐做法
      

  3.   

    其实你的程序跑一段时间之后不响应基本上是:不是所有的线程在退出前都运行了Counter.sub();  那那些退出而没有运行Counter.sub(); 的线程积累到了MAX个
    自然就满了,其他线程就一直等....永远也等不到,因为没有线程再会去Counter.sub(); 了请仔细看你的代码:            finally {
                    try {
                        reader.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    try {
                        streamReader.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    try {
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                Counter.sub(); 这个Counter.sub();应该放到finally里面
      

  4.   

    基本上这种socket程序,都是靠IOException或者socket的timeout来退出的
    所以finally里面要做的事情就比较重要了你的做法是不错的,不过java有个更好的东西,线程池,去看看他的API吧,你会发现,真好用,呵呵
      

  5.   


    补充下
    这样做的目的应该是防止A线程Counter.parse() 得到true之后退出,
    然后B线程Counter.add();回来A线程之后有add()而导致Couter.counter>max吧那这样,parse和add()就是同一个事务,把两件事情放到同一个方法里,更符合逻辑例如
    while(!Counter.getRunTicket())
    {
        sleep();
    }Couter:
    public synchronized static boolean getRunTicket(){
            if(Counter.counter < Counter.max){
                Counter.counter += 1; 
                return true;
            }else{
                return false;
            }
        } 
      

  6.   

    还要补充一下其实这个不放到finally里面也是可以的,这个错误我前两天也遇到了,是因为捕获的不是所有异常而导致程序不是按你的逻辑运行
    遇到错误,如果catch过的这种错误,catch块下面的代码还是会继续执行的,就是说如果是遇到IOException,那么Counter.sub()还是会执行但是,你的catch就仅仅是catch了IOException,其他类型的Excpetion没有catch到
    如果运行中遇到类似于"数组越界","空指针"之类的错误,方法直接就退出了,因为你没有catch这类的异常所以如果你的            catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        reader.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    try {
                        streamReader.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    try {
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                Counter.sub(); 变成 catch(Exception e)  程序也应该没有问题的
      

  7.   

    顺便探讨下程序结构的问题:个人觉得,像这种逻辑的程序,把你所有的业务处理程序段封装成一个方法,例如service()那么,程序逻辑就更清晰的变成:while(!取得运行条件())
    {
            sleep();
    }
    service();
    清理运行条件();再因为你的业务处理是顺序的,下一步需要上一步作为条件,如果上一步(只要有一步)出错,你的业务就无法继续处理
    那么,在这个service()里的所有异常都不要捕获而将它们全部throws出来程序变成:while(!取得运行条件())
    {
            sleep();
    }String result="";
    try{
          result=service(); //service() 正常运行返程return "OK";
          result="OK";      //或者
    }catch(Excpetion e)

           result=e.toString();
    }运行条件等清理();
    log(result);
      

  8.   

    太厉害了,你说的那个  
    catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        reader.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    try {
                        streamReader.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    try {
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                Counter.sub(); 
    应该捕获Exception我也想到了,也改了,可是现在又出现这样的问题,你再帮我看看:
    java.io.IOException: Interrupted system call 
      at gnu.java.net.PlainSocketImpl.accept(gnu.java.net.PlainSocketImpl) (/usr/lib/libgcj.so.5.0.0) 
      at gnu.java.net.PlainSocketImpl.accept(java.net.SocketImpl) (/usr/lib/libgcj.so.5.0.0) 
      at java.net.ServerSocket.implAccept(java.net.Socket) (/usr/lib/libgcj.so.5.0.0) 
      at java.net.ServerSocket.accept() (/usr/lib/libgcj.so.5.0.0) 
      at server.Server.start() (Unknown Source) 
      at server.Server.main(java.lang.String[]) (Unknown Source) 
    这个事socket.accept方法出现的异常,可是这个异常怎么处理啊??
      

  9.   

    google到的:linux内核支持抢占,可以被其他优先级高的进程、驱动程序中断等打断。返回errno   为EINTR。
    一般accept都是在循环中,如果出现这个错误,重新调用accept即可没遇到过,不是很确定,可以尝试:
    while (true) {
    try{
                    Socket s = Server.accept();
                    ServerThread st = new ServerThread(s, db);
                    st.start();
    }catch(IOException e)
    {
        //忽略这个错误
        if(e.getMessage().indexOf("Interrupted system call")!=-1)
        {
             throw e;
         }
    }
    }
      

  10.   

    http://topic.csdn.net/u/20070402/15/27aad8c3-2e12-4ff2-84f2-e87b60b0ee6a.html这贴说最后搞定是ip地址没设对
    serverSocket不用ip只用port吧,呵呵,
    不懂了,要搞定了说一下咯