java中某一个函数或者线程执行完毕后,里面创建的对象会不会被回收?急急急急急急急急急!!!

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java中某一个函数或者线程执行完毕后,里面创建的对象会不会被回收?急急急急急急急急急!!!相关的知识,希望对你有一定的参考价值。

例如

void fun()
String abc="123456";
Vector d=new Vector();
for(int i=0;i<100000;i++)
d.add(abc);




当fun()函数执行完毕后,d以及abc是否被系统自动回收而清除占用的内存?如果不是请教下如何做才能让系统回收占用的内存,谢谢!!
对了还有一个问题,假如我在主函数的while循环中经常使用一个Vector的add操作,当Vector中数量达到一定时例如1000,就执行clear()操作,然后再add,超过1000再clear()。反复如此会不会造成内存泄露??应如何解决clear()时只清除对象没有清除内存的问题?
因为我的程序运行很久后报错了(java heap内存不足什么的)

d会被回收
abc不会 更确切的说是 123456 这个字符串对象不会被回收
java程序里字符串对象一旦被创建就会一直存在就算失去了所有引用也是一样

不会造成泄漏 用了clear() 就等于把引用全都删除了 失去了所有引用的对象(除了字符串对象)会被垃圾处理
参考技术A fun()函数执行完毕后,d以及abc被系统自动回收而清除占用的内存,,这里只是两个对象,能占多大内存,况且方法结束后就会被回收,你的关键代码在for循环,你定义了一个d对象,系统默认分配一个指定内存大小的空间,当循环的时候,内存不够,我记得Vector的好像是自动扩大一倍的地址,直到地址足够大,内存溢出了 参考技术B 暂时不会的,但是你也无法访问到它,在一段时间后,系统会自动回收!追问

麻烦再看一下我的补充问题,谢谢!

追答

会的出现内存泄露,因为clear()操作只是把 你之前Vector的引用消除,但是并没有消除引用对应的那个对象,就好比d.add(abc);执行clear() 清除的事d指向的“abc”的引用,而“abc”仍然存在于内存中!

public voidclear()
从此向量中移除所有元素。此调用返回后,向量将为空(除非抛出了异常)。

追问

说的很有道理!那么我想知道clear()之后也把之前Vector中占用的内存清除,应该怎么做?"abc"我已经不用了,怎么将它从内存中删除?

追答

严格的说,java才去的自动回收机制的!
如果销毁一个对象,只要销毁对这个对象的引用即可,这样java会自动回收那些没有应用的对象!
具体的操作,的看到你的源程序。
String a;
Vector d=new Vector();
a="123";
d.add(a);
a="456";
d.add(a);
a="789";
d.add(a);
d.clear();
a=nulll;
//以后还要继续使用d
这样应该是不会出现内存泄露的

本回答被提问者采纳
参考技术C Vector d=new Vector();你把这句话的意思理解了就行,包括创建了几个对象,分别存在什么地方
手动回收对象的话可以直接把对象置成空,如abc=null,不过我觉得你的问题更多的在设计上,没有哪个程序员会让for循环执行10万次,即使是像你这样做,你完全可以把String自增10万次,让后赋值给Vector对象,而且像这种大数据量的循环,while要比for效率高很多追问

如果我在循环结束后写上abc=null,并且知性d.clear();那么之前Vector d所占用的内存都会被释放吗??

再问一个问题:假如有如下代码

String a;
Vector d=new Vector();
a="123";
d.add(a);
a="456";
d.add(a);
a="789";
d.add(a);
d.clear();
a=nulll;
//以后还要继续使用d
.........

这样还会有内存泄露吗?谢谢了!

java异步操作实例

1.异步操作过程实例:

A.开启一个线程一直执行耗时操作

B.通过每隔多长多件轮询线程是否实行完毕,thread.isCompleted()

C.执行完毕后,通过回调函数返回真实信息

一个调用者在调用耗时操作,不能立即返回数据时,先返回一个取货凭证.然后在过一断时间后
凭取货凭证来获取真正的数据.
 
所以连结调用者和真实数据之间的桥梁是取货凭证.我们先来看它的实现:
 
public class FutureTicket{
 private Object data = null;
 private boolean completed = false;
 
 public synchronized void makeRealData(){
  if(this.complited) return;
  //获取数据的耗时操作.这里用Sleep代替
  try{
   Thread.sleep(10000);
  }catch(Throwable t){}
  this.data = "返回的数据内容";
  this.completed = true;
  notifyAll();
 }
 
 public synchronized Object getData(){
  while(!this.completed)){
   try{
    wait();
   }catch(Throwable t){}
  }
  return this.data;
  
 }
 public boolean isCompleted(){
  return this.completed;
 }
}
 
为了简单化说明(不把它们的关系开得复杂),这里用Objectb代替了真实数据.而真实的实现中
我们应该把makeData放在一个真实数据的类中,然后提供一个方法返回真实数据.这样对于真实
数据的处理和取货凭证解耦.
 
对于这个取货凭证,调用者的如何调用是异步调用的关键:
 
publc class Requester{
 public FutureTicket request(){
  final FutureTicket ft = new FutureTicket();
  
  //在新线程中调用耗时操作
  new Thread(){
   public void run(){
    ft.makeRealData();
   }
  }.start();
  return ft;
 }
}
在新线程中启动耗时操作后,不等待线程的完成立即返回提货单.
 
然后调用者可以根据ft.isCompleted()来调用getData()获取真实数据.
当然对ft.isCompleted()测试可以按规定时间间隔轮巡(极低级的方案),也可以
在条件不满足时wait(),然后等待makeData的notifyAll();这样你就完成了一个
用JAVA模拟的异步操作.
 

改进:
但这样的调用对于调用者来说仍然要继续控制线程操作.如果调用者是一个资深的
程序员,这当然没有问题.但假如我们把对直接数据的处理委托给取货凭证来做.调用
者直接规定对数据的操作,然后由取货凭证来调用规定的操作,这对于调用者是一个很
好的解脱:
 
interface ProcessData{
 public void process(Onject data);
}
 
public MyProcessData{
 public void process(Object data){
  //你不管什么时候起初数据data被获取了.
  //你只要规定如果获取到数据了如何处理
  
  System.out.println(data.toString() + "处理完成...........");
  //insert into dataBase?
 }
}
 
取货凭证在接收调用者请求获取数据时,要知道对获取的数据如何处理的方法:
 
public class FutureTicket{
 private Object data = null;
 private boolean completed = false;
 private ProcessData pd;
 
 public FutureTicket(ProcessData pd){
  this.pd = pd;
 }
 public synchronized void makeRealData(ProcessData pd){
  if(this.complited) return;
  //获取数据的耗时操作.这里用Sleep代替
  try{
   Thread.sleep(10000);
  }catch(Throwable t){}
  this.data = "返回的数据内容";
  this.completed = true;
  notifyAll();
 }
 
 public synchronized void putData(){
  while(!this.completed)){
   try{
    wait();
   }catch(Throwable t){}
  }
  //return this.data;
  //不用返回了,直接处理
  this.pd.process(this.data);
  // alert(?);
  
 }
 

 //这个方法也可以不要了.
 public boolean isCompleted(){
  return this.completed;
 }
}
 
调用:
 
  final FutureTicket ft = new FutureTicket(new ProcessData());
  
  //在新线程中调用耗时操作
  new Thread(){
   public void run(){
    ft.makeRealData();
   }
  }.start();
  ft.putData();
 
OK,你现在可以抽烟,喝酒,泡妞.ft会为你完成所有的工作.

以上是关于java中某一个函数或者线程执行完毕后,里面创建的对象会不会被回收?急急急急急急急急急!!!的主要内容,如果未能解决你的问题,请参考以下文章

JAVA 线程池 其中一个线程执行失败 则线程重新执行或者重新提交任务 急

Java如何判断线程池所有任务是不是执行完毕

C# 如何让线程等待到执行完毕才执行下一个循环

C#多线程: 怎么知道 多个线程 执行完毕了?所有的线程执行完毕后 我要做处理

linux下多进程或者多线程编程的问题。新手,望指教!

如何实现java主线程等待子线程执行完毕之后再执行