精华帖 (0) :: 良好帖 (1) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2008-11-07
最后修改:2008-11-07
wangdi 写道 恩,也就是说造成这个OOM的是因为直接调用JDK1.4的run()方法。主要是不知道Thread里面的exit()方法是什么时候调用的,呵呵。。。
另外关于引用文章提到的线程池,对此有什么影响呢?是否像我说的那样: ---- 就concurrent来说,线程池中线程执行完后,在默认的60s之后就会从线程池中remove,那么传入该线程的MyThread对象也应该在某个时候GC才对哦。 ---- 对线程的使用总是有些战战兢兢,真希望有一天用得得心应手。。。 exit()是private,在Thread内部也没有调用到,我猜测是jvm内部跟踪调用的。 你说的concurrent应该是Douge Lea的jdk1.4并发包吧,Douge Lea是并发专家,写出来的东西既然给了那么个接口应该是值的信赖的。没源码,看看源码吧,可能对execute(Thread)有特殊处理。不过还是推荐使用Runnable接口。 |
|
返回顶楼 | |
发表时间:2008-11-07
呵呵,上源码,没做什么特殊处理,第一个任务来的时候,新增一个线程并执行它,第二个任务来的时候,如果没有线程在任务队列等待,则继续新增一个线程执行它,直到线程池满。如果有线程在任务队列等待,则让它取出去执行。
当一个线程有默认60s时间啥事没做,则把它从线程池中remove。 public void execute(Runnable command) throws InterruptedException { for (;;) { synchronized(this) { if (!shutdown_) { int size = poolSize_; // Ensure minimum number of threads if (size < minimumPoolSize_) { addThread(command); return; } // Try to give to existing thread if (handOff_.offer(command, 0)) { return; } // If cannot handoff and still under maximum, create new thread if (size < maximumPoolSize_) { addThread(command); return; } } } // Cannot hand off and cannot create -- ask for help if (getBlockedExecutionHandler().blockedAction(command)) { return; } } } protected void addThread(Runnable command) { Worker worker = new Worker(command); Thread thread = getThreadFactory().newThread(worker); threads_.put(worker, thread); ++poolSize_; thread.start(); } protected synchronized void workerDone(Worker w) { threads_.remove(w); logger.info("Thread removed from thread pool."); if (--poolSize_ == 0 && shutdown_) { //disable new threads maximumPoolSize_ = minimumPoolSize_ = 0; //notify awaitTerminationAfterShutdown notifyAll(); } // Create a replacement if needed if (poolSize_ == 0 || poolSize_ < minimumPoolSize_) { try { Runnable r = (Runnable) (handOff_.poll(0)); //just consume task if shut down if (!shutdown_) { //add unconditionally and keep the minimum pool size. addThread(r); } } catch (InterruptedException ie) { return; } } } |
|
返回顶楼 | |
发表时间:2008-11-07
会不会被GC,只需要看还有没有被引用!!
所谓内存泄漏,就是忘记了在某个地方还有个引用。 firstTask_ = null; // enable GC 这样的注释本质上就是错误的!!这是掩耳盗铃 对于concurrent,如果传入的还是有其他引用的线程对象,那也肯定不会被GC的! |
|
返回顶楼 | |
发表时间:2008-11-07
从你的源码给出来看,确实没有特殊处理,那么使用execute(Thread)还是会引起OOM的,换成实现Runnable接口了,有条件jrofile一下。
|
|
返回顶楼 | |
发表时间:2008-11-07
timerri 写道 会不会被GC,只需要看还有没有被引用!!
所谓内存泄漏,就是忘记了在某个地方还有个引用。 firstTask_ = null; // enable GC 这样的注释本质上就是错误的!!这是掩耳盗铃 对于concurrent,如果传入的还是有其他引用的线程对象,那也肯定不会被GC的! 同意,在这里根本就没有enable GC,只是firstTask_没有指向任何对象而已,原来的对象还是有被引用的: Runnable task = firstTask_; GC不会回收。 另外,就像上面朋友说的,调用run不会启动一个线程,我认为还是不能按照线程的生命周期来看它什么时候被回收。 如果没有调start(),或许线程连就绪状态还没有吧。 |
|
返回顶楼 | |
发表时间:2008-11-07
呵呵,那个enable GC可不是我加的哦:)
调用run()不会启动线程,但是会在ThreadGroup里面把它加进去。。。 |
|
返回顶楼 | |
发表时间:2008-11-07
最后修改:2008-11-07
线程是不会被GC的,不走完线程的生命周期而直接显式给线程引用赋null是不会得到预期的GC结果的
|
|
返回顶楼 | |
发表时间:2008-11-07
楼上正解!
|
|
返回顶楼 | |
发表时间:2008-11-08
测试方法,不解释了。
public class ThreadDemo { public static void main(String[] args){ ThreadOne one = new ThreadOne("ThreadOne"); ThreadTwo two = new ThreadTwo(); Thread.currentThread().getThreadGroup().list(); one.run(); two.run(); try { //目的是保证one.run()和two.run()都已经执行了。 Thread.sleep(1000); } catch (Exception e) { e.printStackTrace(); } Thread.currentThread().getThreadGroup().list(); one.start(); new Thread(two, "ThreadTwo").start(); try { //目的是保证one.start()和new Thread(two, "ThreadTwo").start()都已经执行了。 Thread.sleep(1000); } catch (Exception e) { e.printStackTrace(); } Thread.currentThread().getThreadGroup().list(); } } class ThreadOne extends Thread { public ThreadOne(String name) { super(name); } public void run() { System.out.println("This is Thread one."); } } class ThreadTwo implements Runnable { public void run() { System.out.println("This is Thread two."); } } |
|
返回顶楼 | |
发表时间:2008-11-08
测试代码:
public class ThreadGc { public static class LargeThread extends Thread { long[] data; public LargeThread(int size) { data = new long[size]; } public void run() { // do nothing } } public static void main(String[] args) { for (int i = 0; i < 1000000; i++) { new LargeThread(1000000); } } } 看是否出现OOM? 在Jdk6和Jdk1.5.0_16下用Ubuntu64位系统测的结果是会回收的。 在Jdk1.4.2_16下用windows xp系统测的结果是没有回收的,会OOM。也可以打开-verbose:gc来验证 |
|
返回顶楼 | |