Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/361.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在多处理过程中如何共享变量感到困惑_Java_Multiprocessing - Fatal编程技术网

对Java在多处理过程中如何共享变量感到困惑

对Java在多处理过程中如何共享变量感到困惑,java,multiprocessing,Java,Multiprocessing,我刚开始使用java,如果这个问题的答案很明显,我很抱歉。我真的不知道如何在java中共享变量。我一直在玩python,想尝试将一些代码移植到Java,以便更好地学习语言。我的很多代码都是移植的,但我不确定多处理和变量共享在Java中究竟是如何工作的。我的过程不是磁盘绑定的,并且使用了大量cpu和搜索列表 在Python中,我可以这样做: from multiprocessing import Pool, Manager manager = Manager() shared_list = man

我刚开始使用java,如果这个问题的答案很明显,我很抱歉。我真的不知道如何在java中共享变量。我一直在玩python,想尝试将一些代码移植到Java,以便更好地学习语言。我的很多代码都是移植的,但我不确定多处理和变量共享在Java中究竟是如何工作的。我的过程不是磁盘绑定的,并且使用了大量cpu和搜索列表

在Python中,我可以这样做:

from multiprocessing import Pool, Manager
manager = Manager()
shared_list = manager.list()
pool = Pool(process=4) 
for variables_to_send in list_of_data_to_process:
       pool.apply_async(function_or_class, (variables_to_send, shared_list))
pool.close()
pool.join()
我一直很难弄清楚如何在Java中进行这样的多处理和共享。这帮助我理解了一点,通过代码实现runnable是如何有帮助的,我开始认为java可能会自动多进程线程纠正我,如果我错了,我读到线程一旦超过一个cpu的容量,就会被转移到另一个cpu?oracle文档似乎更关注线程而不是多处理。但它并没有解释如何在进程之间共享列表或其他变量,并使它们保持足够的同步

有什么建议或资源吗?我希望我在寻找错误的东西多处理java,希望这和我上面的代码一样简单或简单


谢谢

线程和进程之间有一个重要的区别,您现在正在运行它:除了一些例外,线程共享内存,但进程不共享内存

请注意,真正的操作系统几乎可以解决我要说的所有问题,但这些特性并没有在典型情况下使用。因此,要启动一个新进程,您必须以某种方式用*nix上的系统调用克隆当前进程,这是fork,然后用*nix上的另一个系统调用替换子进程的代码、堆栈、命令行参数等,这是系统调用的exec系列。Windows大致相当于这两个系统调用,所以我所说的一切都是跨平台的。此外,Java运行时环境在幕后处理所有这些系统调用,如果没有JNI或其他互操作技术,您就无法真正自己执行它们

关于这个模型,有两件重要的事情需要注意:子进程不共享父进程的地址空间,并且子进程的整个地址空间在exec调用中被替换。因此,父进程中的变量对子进程不可用,反之亦然

线程模型完全不同。线程有点像lite进程,因为每个线程都有自己的指令指针,在大多数系统上,线程由操作系统调度器调度。但是,线程是进程的一部分。每个进程至少有一个线程,进程中的所有线程共享内存

现在谈谈你的问题:


正如您的代码示例所示,Python多处理模块只需很少的努力就可以生成进程。在Java中,生成新进程需要更多的工作。它涉及使用或创建新对象。然后,您可以通过管道将字符串传输到子进程,获取其输出,等待其退出,以及其他一些通信原语。我建议编写一个程序作为协调程序,启动每个子进程,并编写一个与示例中的函数\或\类大致对应的辅助程序。协调器可以打开辅助程序的多个副本,为每个副本分配一个任务,并等待所有辅助程序完成。

您可以使用Java线程来实现此目的。您需要创建一个用户定义的类。该类应该具有setter方法,通过该方法可以设置共享列表对象。实现Runnable接口并在run方法中执行处理任务。你可以在网上找到很好的例子。如果您正在共享共享列表的同一实例,则需要确保对该变量的访问是同步的

这不是在java中使用线程的最简单的方法,但它与您发布的python代码完全不同。task类是可调用接口的实例,它有一个调用方法。当我们创建10000个任务实例中的每一个实例时,我们会向它们传递对同一列表的引用。因此,当调用所有这些对象的call方法时,它们将使用相同的列表

我们在这里使用4个线程的固定大小的线程池,因此我们提交的所有任务都会排队等待线程可用

public class SharedListRunner {
    public void RunList() {
        ExecutorService executerService = Executors.newFixedThreadPool(4);
        List<String> sharedList = new List<String>();
        sharedList.add("Hello");
        for(int i=0; i < 10000; i++)
            executerService.submit(new Task(list));
    }
}

public class Task implements Callable<String> {

    List<String> sharedList;    

    public Task(List<String> sharedList) {
            this.sharedList = sharedList;
    }

    @Override
    public String call() throws Exception {
            //Do something to shared list
            sharedList.size();  
            return "World";
    }
}

任何时候都有4个线程正在访问列表。如果您想进一步挖掘访问该列表的4个Java线程,那么服务于这4个Java线程的操作系统线程可能会更少,处理器线程也会更少,通常每个cpu核心2或4个

当我运行上面的python代码时,我在上面的示例中创建多处理器,这些是共享同一列表的唯一进程。有没有一种方法可以在Java中轻松实现相同的结果?Java虚拟机作为单个进程运行
在内部管理线程。不能在JVM中生成进程。但是,使用多个处理器并不一定要这样做。@Lostsoul您可以使用RMI或其他进程间通信机制在进程之间传递列表,但正如我在回答中所说,Java并没有提供任何比Python的多处理器更易于使用的东西。RMI的问题是,由RMI库处理的序列化和反序列化可能会非常昂贵。我推荐的协调方法通过写入Process.getInputStream的返回值,强制您将任务描述写入工作进程的stdin,但除非每个子进程都使用整个列表,否则这可能会更有效。@AdamMihalcin True关于从Java生成进程,但您为什么需要这样做呢。一个拥有大量内存和良好管理线程的JVM与单独的进程一样好吗?Voo的想法是正确的,在Java中解决这个问题不需要进程。@UsmanIsmail要确切知道,您必须开发多个解决方案并比较它们之间的性能。只要你小心并发控制,我同意单个JVM通常比单独的进程好。嗨,乌斯曼…我对Java非常陌生。实际上,我今天开始,我如何运行这些类?我知道这是基本的,但我试着将它们放在一个名为task.java的文件中,但它不起作用,一个名为SharedListRunner的文件也不起作用。我想我必须从另一个文件调用它们,但不确定我需要做什么才能调用它们我知道我可以导入这两个文件,但是接下来呢?类名必须与文件名匹配,这样您将有两个文件:SharedListRunner.java和Task.java。我也跳过了导入声明。请在尝试之前阅读一些基本教程多线程程序这里有一些复杂之处。