解决方案 »
- 邮箱验证的正则表达式
- 新手方法重载参数传递疑惑?
- java继承的问题
- 我把数据库里的数据存到了一个BufferedInputStream ,怎么分离出他原来的数据啊?有没有知道的,谢谢!
- 请问JAVA如何根据图片画不规则的窗体?用JDK5.0
- 用java怎么处理多级部门的显示
- 为什么.isFile()返回的是FALSE 呢,明明是TXT文件啊?
- 如何儲存jTextPane中的文字入database
- 枚举类有valuse()这个方法吗?我在jdk5doc里搜索enum,他没有这个方法,难道是他继承别人的?那又是继承谁的?
- java中基于socket的问题
- JAVA执行LINUX命令的问题
- 如何把Graphics画好的图像做成BufferImage
对 Timer 对象最后的引用完成后,并且 所有未处理的任务都已执行完成后,计时器的任务执行线程会正常终止(并且成为垃圾回收的对象)。但是这可能要很长时间后才发生。楼主在run函数最后加一句 System.gc(); 试试
之后,交由Timer进行(run方法的)的方法调用。这时,该MyTimerTask对象,被Timer所持有,由于schedule方法是重复执行的方法,后台会有一个子线程持有Timer对象,所以,Timer对象尽管在主线程中没被引用,但是,它会被后台子线程所引用,而不会得到垃圾回收。之后,当Timer被触发,调用MyTimerTask的run方法时,run方法又会创建Tiemr实例,生成子线程持有本身而不释放。程序的最终结果,就是在程序的后台,不停地创建Timer子线程,并且,这些Timer的实例(对象)得不到垃圾回收,当然,Timer提交的任务对象(MyTimerTask对象)被Tiemr持有而不会被垃圾回收,最终,随着时间的推移,JVM内存不足,表现的现象就是内存泄露。
那请问哥们,
new Timer().schedule(new MyTimerTask(), 0+count*2);
这句代码创建出来的Timer线程调度后,
new MyTimerTask()这个对象又被谁引用么?既然创建了很多Timer后台线程为什么我手动掉gc能清理垃圾这些Timer线程(因为空闲内存没继续减少,所以可以判断Timer对象也被回收了)最后,怎么不自己手动调用gc,让JVM自动回收垃圾
是延时调用而不是重复调用,刚才,没看清楚代码。
重复调用的方法是:Timer.schedule(TimerTask task, long delay, long period),最后那个参数是重复调用的周期。延时调用的task对象,当调用完成之后,就不会被Timer的线程实例所持有了,这时,可以被垃圾回收。
由于task对象可以被回收,那么,里面产生的Timer对象,也会有被回收的可能。程序设计当中,是允许程序员进行gc操作的,但是,gc操作只是通知JVM进行垃圾回收,至于JVM是否真的进行垃圾回收,要根据JVM的回收策略进行触发。
所以说,楼主可以手动gc,这没什么错的地方。最后,楼主 Exception in thread "Timer-3976"
java.lang.OutOfMemoryError: unable to create new native thread
这个日志的信息,是表示的内存不足了,无法创建更多的线程实例。
这里,我想多说一句,我们的程序,应该尽量的提高线程的利用。一个程序,没必要创建将近4千个线程来做事情吧,我们可以创建尽量少的线程,(比如2~4个)来处理这些task,这些task只是调用的时间不同,而大多数情况下,不需要并发处理,即使要并发处理,也不用变态到几千个同时来。
1、内存分配越多,所能创建线程数越少;
2、线程数太多,系统运行能效反而下降。关于第一个问题,可以参见:
http://sesame.iteye.com/blog/622670关于第二个问题:
不要滥用线程,如果你想使用大规模任务处理的话,用线程池更好些。
java.util.concurrent 这个包里已经分装好功能更强大的多线程并发包