Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中的多线程垃圾收集:在GC外部共享对象?_Java_Multithreading_Garbage Collection - Fatal编程技术网

Java中的多线程垃圾收集:在GC外部共享对象?

Java中的多线程垃圾收集:在GC外部共享对象?,java,multithreading,garbage-collection,Java,Multithreading,Garbage Collection,考虑以下方法: public void Parse(String[] S, Objects[] O) throws IOException { final int N_THREADS = Runtime.getRuntime().availableProcessors(); BlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<Runnable>(20); RejectedEx

考虑以下方法:

public void Parse(String[] S, Objects[] O) throws IOException {
    final int N_THREADS = Runtime.getRuntime().availableProcessors();
    BlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<Runnable>(20);
    RejectedExecutionHandler rejectedExecutionHandler = new ThreadPoolExecutor.CallerRunsPolicy();
    ThreadPoolExecutor service =  new ThreadPoolExecutor(N_THREADS, N_THREADS, 0L, TimeUnit.MILLISECONDS, blockingQueue, rejectedExecutionHandler);
    final SomeObject RO = new SomeObject();
    for(String s : S){
        service.execute(new Runnable() {
            public void run() {
                // initialize variables
                for (Object o : O) {
                        V ps = RO.apply(sentence);
                        //more work on ps 
                }
                File f = new File("something");
                FileWriter fw = null;
                try {
                    fw = new FileWriter(f.getAbsoluteFile());
                    BufferedWriter bw = new BufferedWriter(fw);
                } catch (IOException e) {
                    System.out.println(f.getAbsoluteFile());
                }
                BufferedWriter bw = new BufferedWriter(fw);
                for (SentenceAnnotation entry : annotations) {
                    try {
                        bw.write(entry.toString());
                        bw.newLine();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }

                try {
                    bw.flush();
                    bw.close();
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }
    service.shutdown();
    while (!service.isTerminated()) {
    }
    long timeEnd = System.currentTimeMillis();
}
公共void解析(字符串[]S,对象[]O)引发IOException{
final int N_THREADS=Runtime.getRuntime().availableProcessors();
BlockingQueue BlockingQueue=新阵列BlockingQueue(20);
RejectedExecutionHandler RejectedExecutionHandler=new ThreadPoolExecutor.CallerRunPolicy();
ThreadPoolExecutor服务=新的ThreadPoolExecutor(N_线程,N_线程,0L,TimeUnit.毫秒,blockingQueue,rejectedExecutionHandler);
最终SomeObject RO=新的SomeObject();
用于(字符串s:s){
service.execute(新的Runnable(){
公开募捐{
//初始化变量
用于(对象o:o){
V ps=适用(句子);
//更多关于ps的工作
}
文件f=新文件(“某物”);
FileWriter fw=null;
试一试{
fw=新文件编写器(f.getAbsoluteFile());
BufferedWriter bw=新的BufferedWriter(fw);
}捕获(IOE异常){
System.out.println(f.getAbsoluteFile());
}
BufferedWriter bw=新的BufferedWriter(fw);
for(句子注释条目:注释){
试一试{
write(entry.toString());
换行符();
}捕获(IOE异常){
e、 printStackTrace();
}
}
试一试{
bw.flush();
bw.close();
fw.close();
}捕获(IOE异常){
e、 printStackTrace();
}
}
});
}
service.shutdown();
而(!service.isTerminated()){
}
long-timeEnd=System.currentTimeMillis();
}

其中S是一个大数组(数十万),O的长度为50。我的问题是关于RO对象的。它是在外部创建的,如果您愿意,它将被所有线程“共享”。现在,当这段代码运行了一段时间后,堆空间就用完了,这让我感到困惑。我倾向于认为RO对象仍然保持其他已完成的Runnable活动,并慢慢消耗内存。这是真的吗?我已经使用“free-m”监控了linux系统(最新版本的OracleJDK)的内存消耗,我可以缓慢但肯定地看到内存消失。非常感谢您给我的建议。

据我所知,您显示的代码没有任何可疑之处

最好的选择是获取应用程序的堆转储,然后检查内存中的内容

您可以使用jdk的
bin
文件夹中的JVisualVM生成堆转储并对其执行基本分析。例如,您肯定会发现许多关于堆分析的问题


在这段代码中,您正在泄漏一个未关闭的
BufferedWriter
。在
try
子句的作用域中创建第一个,但不关闭它。引用消失,但运行时创建的任何本机句柄都不会被释放。您没有注意到这一点,因为您随后立即为同一文件创建了一个新的
BufferedWriter

您似乎创建了两次BufferedWriter。我不太确定这里的范围问题,但在我看来,这甚至不应该正确编译。尝试在“Try”块之前声明BufferedWriter,只需在不进行第二次创建的情况下使用它:

        BufferedWriter bw;            
        try {
            fw = new FileWriter(f.getAbsoluteFile());
            bw = new BufferedWriter(fw);
        } catch (IOException e) {
            System.out.println(f.getAbsoluteFile());
        }
        for (SentenceAnnotation entry : annotations) {
            try {
                bw.write(entry.toString());
                bw.newLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
如果我是对的,那么您就不会生成“成千上万”不必要的BufferedWriter对象。但不能保证

作为一个风格问题,我会考虑把“尝试”块组合成一个,使用一个“catch”而不是两个。当然,除非您打算给出不同的错误消息

希望有帮助

阿希姆

        BufferedWriter bw;            
        try {
            fw = new FileWriter(f.getAbsoluteFile());
            bw = new BufferedWriter(fw);
        } catch (IOException e) {
            System.out.println(f.getAbsoluteFile());
        }
        for (SentenceAnnotation entry : annotations) {
            try {
                bw.write(entry.toString());
                bw.newLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }