package com.javatest.gc.lixuan; import java.lang.ref.SoftReference; public class GCTest { public static void main(String[] args) { final int MAX_THREAD_NUM = 20; int threadTotalNum = 0; for (; threadTotalNum < MAX_THREAD_NUM; threadTotalNum++) { NewThread nt = new NewThread(); NewThread.setThreadNum(); nt.start(); // nt = null; try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } // System.out.println("I'm out!"); } } class NewThread extends Thread { public static Integer threadNum = 0; public int mNum = 0; private int mStringBuilderNum = 0; private String str = "nihao!"; public NewThread() { synchronized (NewThread.threadNum) { mNum = threadNum; } } public void run() { while (true) { try { int n = 10000; StringBuilder[] sb = new StringBuilder[n]; SoftReference<StringBuilder[]> sf = new SoftReference<StringBuilder[]>(sb); for (int i = 0; i < n; i++) { sb[i] = new StringBuilder(); sb[i].append(str); Thread.sleep(10); System.out.println("Thread number:" + mNum); } System.out.println("Thread number:" + mNum +"("+this.getId()+")"+ " new sb numbers:" + mStringBuilderNum++); // Thread.sleep(1000); } catch (Exception e) { e.printStackTrace(); } } } public static void setThreadNum() { synchronized (threadNum) { threadNum++; } } }
好了,顺带的第2个问题也知道了,那么堆溢出是怎么回事呢?貌似这里不会产生啊,可以看到其使用情况(VisualVM好用的软件啊)截图如下:
垃圾回收器及时收回内存。有无休眠直接影响CPU的占用。后图多了个软引用,可以看到回收的延迟。
从代码中还看到使用了SoftReference,这个其实就是三种引用:弱引用、软引用、虚引用;大概意思就是弱引用可以再对象置null时和垃圾回收之前延长点时间再回收,和finalize类似,只是finalize中包含了回收前执行的方法(主要是在调用了C/C++中的代码要执行的内存释放);软引用多用于缓冲区,在内存告急时才会被释放;虚引用则是主要用来跟踪对象被垃圾回收的活动,和引用队列(ReferenceQueue)联合使用,在回收前做点操作(上面只是试了软引用,从截图也能看出些东西来,详细的可以看参考3)。但是这样堆溢出还是没有找到原因,还是继续寻找吧。