最近用java线程写了一个每隔10分钟写日志文件的
程序放在solaris上运行,老是出现问题,又没什么
规律,有时线程连续运行7天就死悄悄了,有时3,4天,
有时个把月才死,死之后又没什么错误,又没内存
泄漏,也可以保证不会存在死锁,用JProfiler也没
发现什么可疑之处,郁闷,害得客户老要重启。

解决方案 »

  1.   

    运行环境:
    solaris9(SPARC)中文操作系统
    JDK1.4(solaris9自带的)
      

  2.   

    哪位用JAVA写过7*24不间断运行的实时系统(例如数据采集之类的),
    并且至少能连续运行1个月不出问题的,
    好给我个安慰,我在java上花了好大功夫(光是买书都花了2000多RMB),
    现在用得越来越不顺手了,希望是我的错,不是JAVA的错。
      

  3.   

    顺便在这里我还问了个问题,都一个月了,真不知道是不是高手嫌分少了?
    http://community.csdn.net/Expert/topic/3932/3932563.xml?temp=.9485437
      

  4.   

    顶,非内存泄露,那有可能是等待的时候sleep抛出异常了。这个问题我也没碰到过
      

  5.   

    我是这样sleep的;
    try {
       sleep(600000L); 
    }catch(Exception e) {}
    因为该日志线程是独立的,跟其他线程没任何关系,
    就是一个死循环,所以并没有捕获异常,或许是因为
    线程sleep太久了,偶尔会发生异常,是不是OS或VM
    把线程给干掉了?
      

  6.   

    大哥,怎么用线程Sleep?? 用Timer加TimerTask线程
      

  7.   

    兄弟,怎么能这样的,拿肯定出错的,,用timer和TimerTask类,,,
    timer.scheduleAtFixedRate(wApp,beginDate,24*60*60*1000);
    这里wApp是你的计划类的,在网上找找很多的..
      

  8.   

    大哥,怎么用线程Sleep?? 用Timer加TimerTask线程
    =============================================
    wpx80(wpx80) 大虾能否讲讲其中奥妙!
    另外Timer是javax.swing.Timer?还是java.util.Timer?
      

  9.   

    import java.util.TimerTask;public class TakeWeather extends TimerTask {
      public void run() {
       System.out.println("this is test!!");
    }
    }import java.util.Timer;public class WeatherApp {
          public Timer timer;
        public TakeWeather wApp;
      public void start(){
                  timer=new Timer();
                wApp=new TakeWeather();
                timer.scheduleAtFixedRate(wApp,0,5*1000);
    }
        public static void main(String[] args) {
            try{
                WeatherApp app=new WeatherApp();
                app.start();
            }catch(Exception e){}
        }
    }
    这样,每个5秒钟打印一条数据...
      

  10.   

    tomcat 该是java 的吧,还有那没多java 的server ,都可以运行很稳定的啊,运行好几个月都没有问题的。
      

  11.   

    谢谢各位!也谢谢luorose(luorose) 给出的代码!不过谁能说说用Thead.sleep()与用timer.scheduleAtFixedRate()
    各有什么好处和坏处?
    为什么Thead就不能sleep太久呢?难道timer.scheduleAtFixedRate()
    将间隔设置10分钟以后就一定不出问题吗?我查了一下API源代码Thead类用到了native,Timer类好像没看到有native?
      

  12.   

    既然你Sleep这么长时间,用操作系统带的计划任务管理方法多好!linux下是用crontab,solaris不知道,但我相信肯定有类似方法。
      

  13.   

    既然你Sleep这么长时间,用操作系统带的计划任务管理方法多好!linux下是用crontab,solaris不知道,但我相信肯定有类似方法。
    ========================================================
    我只想确认将线程Sleep这么长时间是否存在问题,
    solaris下也有crontab,但并不是最终目的,
    因为我所举的只是一个最简单的例子,真实系统中的功能用计划任务实现并不理想。我看JDK里的API说明,它并没说有时间限制。
      

  14.   

    好给我个安慰,我在java上花了好大功夫(光是买书都花了2000多RMB)
    确实是真的动了功夫!^_^我感觉这个情况用java.util.Timer类来定时运行TimerTask 是个好的办法!
    至于楼主想探个究竟为什么Thread出问题,是否jvm在客户那里有可能被停止过!
      

  15.   

    你完全没必要非sleep那么久阿。用this.wait,别等那么久,大不了多循环几次。不过对于java的线程,我的一般做法是另外用一个线程来检查线程的状态,发现不正常了就重新起线程。
      

  16.   

    至于楼主想探个究竟为什么Thread出问题,是否jvm在客户那里有可能被停止过!
    ======================================================================
    可以确定jvm没停过,因为其他线程并没有死,
    今天重新改了一下系统

    try {
       sleep(600000L); 
    }catch(Exception e) {}
    改成
    try {
       sleep(600000L); 
    }catch(Exception e) {System.out.println(e);}
    重新确认一下到低是否是sleep引出的问题,
    并开了一个监控线程,每格20秒钟,打印当前活动线程
      

  17.   

    你完全没必要非sleep那么久阿。用this.wait,别等那么久,大不了多循环几次。不过对于java的线程,我的一般做法是另外用一个线程来检查线程的状态,发现不正常了就重新起线程。
    ========================================================================
    因为我所举的只是一个独立线程,不需要wait,notify.我看过人民邮电出版社的<<JAVA线程编程>>
    中国电力出版社的<<JAVA线程(第二版)>>以及CoreJava2 II
    作者都没提到这些注意事项,sun的JDK文档也没说,真是郁闷...我现在都在想自己到底是不是适合写程序了,
    java断断续续学了差不多三年了,用也用了很久了,书也看了N多,什么
    java与模式,JVM,安全,J2ee的方方面面,甚至连J2ME都看了,
    现在反而用起来越来越不顺心,
    跟大家说个我找BUG的笑话,为了找出系统不定期的OutOfMemoryError
    我差不多花了一年,
    我们的系统中有这样一段程序(简化了)import java.net.Socket;
    public class SocketProxy extends Thread {
    ....
    private Socket socket=null; public boolean connect() {
    //主要用来连接Socket,初始IO
    } public void run() {
    connect();
    }
    }public class Test1 extends Thread {
    public static void main(String[] args) {
    Test1 test1=new Test1();
    test1.start();
    }
    public void run() {
    while(true) {
    SocketProxy sp=new SocketProxy();
    sp.start();
    ...
    sleep(20000);
    ....
    }
    }
    }public class Test2 extends Thread {
    public static void main(String[] args) {
    Test2 test2=new Test2();
    test2.start();
    }
    public void run() {
    while(true) {
    SocketProxy sp=new SocketProxy();
    sp.connect();
    ...
    sleep(20000);
    ....
    }
    }
    }之前因为从不用Profiler,所以找了大半年都找不到哪里错了,
    后来费了好大功夫下了个JProfiler,细细观察在Test2中分配
    的SocketProxy sp竟然越new越多,而在Test1中分配
    的SocketProxy sp会时不时的会回收一下,
    最后把SocketProxy类改成这样
    import java.net.Socket;
    public class SocketProxy {
    ....
    private Socket socket=null; public boolean connect() {
    //主要用来连接Socket,初始IO
    }
    }
    再Profiler一下Test2,分配
    的SocketProxy sp也会时不时的会回收一下了,最后得出一个结论:
    如果要new一个继承了Thread的类的实例,如果不调用
    start(),GC不管事,new再多它也不理,直到OutOfMemoryError。或许是我太蠢了,干吗要这么用,或许哪还有个开关我没设好。
      

  18.   

    以下是测试例子,哪位有类似JProfiler的工具的可能尝试一下(最好将JVM机的最大内存设为2M)
    其中Test2类是有问题的,SocketProxy sp的实例会不断增加,GC不会回收
    (只可惜CSDN不能贴图);public class SocketProxy extends Thread {
    public void connect() {
    System.out.println(new java.util.Date());
    } public void run() {
    connect();
    }
    }public class Test1 extends Thread {
    public static void main(String[] args) {
    Test1 test1=new Test1();
    test1.start();
    }
    public void run() {
    while(true) {
    SocketProxy sp=new SocketProxy();
    sp.start();
    try
    {
    sleep(50);
    }
    catch (Exception e) {}
    }
    }
    }public class Test2 extends Thread {
    public static void main(String[] args) {
    Test2 test2=new Test2();
    test2.start();
    }
    public void run() {
    while(true) {
    SocketProxy sp=new SocketProxy();
    sp.connect();
    try
    {
    sleep(50);
    }
    catch (Exception e) {}
    }
    }
    }public class SocketProxy3 {
    public void connect() {
    System.out.println(new java.util.Date());
    }
    }public class Test3 extends Thread {
    public static void main(String[] args) {
    Test3 test3=new Test3();
    test3.start();
    }
    public void run() {
    while(true) {
    SocketProxy3 sp=new SocketProxy3();
    sp.connect();
    try
    {
    sleep(50);
    }
    catch (Exception e) {}
    }
    }
    }
      

  19.   

    怀疑不是
    try {
       sleep(600000L); 
    }catch(Exception e) {}
    的问题。 其他代码呢/?比如写日志文件在哪儿呢
      

  20.   

    线程对象是不归gc收集的,需要程序员自己写!一个常用的方法在thinking in java里有!
      

  21.   

    另外start()的写法值得商榷!
    一般在构造函数里写start()函数,或者加个旗标判断!
      

  22.   

    以前我在SOLARIS上也写过类似的代码,每隔一段时间从日志文件中取信息(和你说的每十分钟写日志差不多),不过代码写在后台,是用C++ FORK()出进程作为一个SERVER端的DAEMON,以进程的方式SLEEP,然后在前台JAVA代码中NATIVE调用。不知道这种方式适不适合你用了。个人感觉这种形式比较稳定。
      

  23.   

    Timer类用的是Object.wait(long)来计时的,比较精确,至于是否会出错就不知道了。timer.scheduleAtFixedRate()在处理需要固定频率的地方:
    例如:用Thread.sleep(1)计数1秒会少于1000,而用timer.scheduleAtFixedRate()
    来计数会刚好1000。
      

  24.   

    线程对象是不归gc收集的,需要程序员自己写!一个常用的方法在thinking in java里有!
    ================================
    没看thinking in java这本书,找机会看看。谢谢!!
      

  25.   

    以前我在SOLARIS上也写过类似的代码,每隔一段时间从日志文件中取信息(和你说的每十分钟写日志差不多),不过代码写在后台,是用C++ FORK()出进程作为一个SERVER端的DAEMON,以进程的方式SLEEP,然后在前台JAVA代码中NATIVE调用。不知道这种方式适不适合你用了。个人感觉这种形式比较稳定。
    =========================
    C++不太熟,有时间再补补,不过还是非常感谢您提的建议!
      

  26.   

    另外start()的写法值得商榷!
    一般在构造函数里写start()函数,或者加个旗标判断!
    ===========================
    调用线程start()的地方应该没什么问题的,我看一些开源的代码也不一定
    就在构造函数里写。