精华帖 (0) :: 良好帖 (1) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2008-11-07
最后修改:2008-11-07
http://www.iteye.com/topic/11217?page=1
基本同:问题主要是关于Thread和Runnable的。在我们项目里面用一般的Runnable不会有问题,但是用Thread,时间长了就会oom。 1、当一个类继承Thread,不调用它的run()方法而是调用start()方法的话,使用完后它能被GC吗? public class MyThread extends Thread{ public void run();{ //do something. } } public static void main(String[] args){ Thread t = new MyThread(); t.run(); //do another thing. } 2、如果能被回收,如果这个线程是通过concurrent的线程池调用的话,情况还是这样吗? pooledExecutor.execute(new MyThread()); 在concurrent的线程池中,执行传入的Runnable,是直接执行它的run方法,而不是把这个Runnable新起一个线程来执行: protected class Worker implements Runnable { protected Runnable firstTask_; protected Worker(Runnable firstTask) { firstTask_ = firstTask; } public void run() { try { Runnable task = firstTask_; firstTask_ = null; // enable GC if (task != null) { task.run(); task = null; } while ( (task = getTask()) != null) { task.run(); task = null; } } catch (InterruptedException ex) { } // fall through finally { workerDone(this); } } } 在上面的文章中,有位兄台的回复: 引用 此处thread 不会被回收我想情况应该是线程池的缘故,app server会把线程存入池中优化性能,在池中的线程是不会被gc的, servlet执行完毕后该servlet所在线程会被线程池回收,所以不会被gc,所以t 肯定也不会被gc。
就concurrent来说,线程池中线程执行完后,在默认的60s之后就会从线程池中remove,那么传入该线程的MyThread对象也应该在某个时候GC才对哦。为啥,它就不GC呢? ....日本人,java code里面的code没办法加高亮。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2008-11-07
你是如何得知它没有被gc的呢?
|
|
返回顶楼 | |
发表时间:2008-11-07
LZ,还是把线程的概念想清楚了, 再来问吧。 Thread和Runnable 这2个东西的区别在那儿你不知道的话, 估计你很难明白。
pooledExecutor.execute(new MyThread()); 执行是什么, 要看清楚, 为什么泄露我不知道, 但是, pooledExecutor接受的Runnable的接口, 不使用THREAD接口吧? |
|
返回顶楼 | |
发表时间:2008-11-07
sdh5724 写道 LZ,还是把线程的概念想清楚了, 再来问吧。 Thread和Runnable 这2个东西的区别在那儿你不知道的话, 估计你很难明白。
pooledExecutor.execute(new MyThread()); 执行是什么, 要看清楚, 为什么泄露我不知道, 但是, pooledExecutor接受的Runnable的接口, 不使用THREAD接口吧? 呵呵,兄台大意了,JDK 1.4源码: public class Thread implements Runnable 也就是说:Thread也是Runnable |
|
返回顶楼 | |
发表时间:2008-11-07
timerri 写道 你是如何得知它没有被gc的呢?
没有被GC是OOM之后分析出来的。。。这个结论我相信没错,因为除了我们这儿遇到之外,我引用的帖子里面也谈到了这点。 |
|
返回顶楼 | |
发表时间:2008-11-07
这个问题会跟jdk版本有关,你引用的帖子里的jdk的确把thread加入到了thread group里,但是在新的jdk1.6中已经改变了这种方式,变成了仅仅计数而不添加到group里。
以这种方法实现的thread,无论是否start都将被正确收集。 如果你确保你的jdk版本没有问题,那么oom可能会是别的问题引起 |
|
返回顶楼 | |
发表时间:2008-11-07
最后修改:2008-11-07
timerri 写道 这个问题会跟jdk版本有关,你引用的帖子里的jdk的确把thread加入到了thread group里,但是在新的jdk1.6中已经改变了这种方式,变成了仅仅计数而不添加到group里。
以这种方法实现的thread,无论是否start都将被正确收集。 如果你确保你的jdk版本没有问题,那么oom可能会是别的问题引起 采用引用计数,有无链接给出?还是你的猜测?我看了下jdk6中的Thread源码,改了一个地方,将 group.add(this) 这行从构造函数中移到了start方法: public synchronized void start() { /** * This method is not invoked for the main method thread or "system" * group threads created/set up by the VM. Any new functionality added * to this method in the future may have to also be added to the VM. * * A zero status value corresponds to state "NEW". */ if (threadStatus != 0) throw new IllegalThreadStateException(); group.add(this); //这里 start0(); if (stopBeforeStart) { stop0(throwableFromStop); } } |
|
返回顶楼 | |
发表时间:2008-11-07
timerri 写道 这个问题会跟jdk版本有关,你引用的帖子里的jdk的确把thread加入到了thread group里,但是在新的jdk1.6中已经改变了这种方式,变成了仅仅计数而不添加到group里。
以这种方法实现的thread,无论是否start都将被正确收集。 如果你确保你的jdk版本没有问题,那么oom可能会是别的问题引起 我的JDK是1.4,在构造方法里面调用的 private void init(ThreadGroup g, Runnable target, String name,long stackSize)方法确实把当前对象加到了ThreadGroup里面。。。 g.add(this); 我想知道就是,这儿在构造方法里面添加到ThreadGroup里面,但是却没有调用start()方法而是调用run()方法会造成oom吗? |
|
返回顶楼 | |
发表时间:2008-11-07
最后修改:2008-11-07
wangdi 写道
timerri 写道
这个问题会跟jdk版本有关,你引用的帖子里的jdk的确把thread加入到了thread group里,但是在新的jdk1.6中已经改变了这种方式,变成了仅仅计数而不添加到group里。
以这种方法实现的thread,无论是否start都将被正确收集。 如果你确保你的jdk版本没有问题,那么oom可能会是别的问题引起 我的JDK是1.4,在构造方法里面调用的 private void init(ThreadGroup g, Runnable target, String name,long stackSize)方法确实把当前对象加到了ThreadGroup里面。。。 g.add(this); 我想知道就是,这儿在构造方法里面添加到ThreadGroup里面,但是却没有调用start()方法而是调用run()方法会造成oom吗?
/** * This method is called by the system to give a Thread * a chance to clean up before it actually exits. */ private void exit() { if (group != null) { group.remove(this); group = null; } ... } |
|
返回顶楼 | |
发表时间:2008-11-07
恩,也就是说造成这个OOM的是因为直接调用JDK1.4的run()方法。主要是不知道Thread里面的exit()方法是什么时候调用的,呵呵。。。
另外关于引用文章提到的线程池,对此有什么影响呢?是否像我说的那样: ---- 就concurrent来说,线程池中线程执行完后,在默认的60s之后就会从线程池中remove,那么传入该线程的MyThread对象也应该在某个时候GC才对哦。 ---- 对线程的使用总是有些战战兢兢,真希望有一天用得得心应手。。。 |
|
返回顶楼 | |