Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/347.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

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 具有循环引用的大型图的并行爬行_Java_Multithreading_Algorithm_Concurrency_Graph Theory - Fatal编程技术网

Java 具有循环引用的大型图的并行爬行

Java 具有循环引用的大型图的并行爬行,java,multithreading,algorithm,concurrency,graph-theory,Java,Multithreading,Algorithm,Concurrency,Graph Theory,简而言之:我想以并行方式处理带有循环引用的大型图。而且我也无法访问完整的图形,我必须在其中爬行。我想组织有效的队列来做到这一点。我很感兴趣,有什么最佳实践可以做到这一点吗 我试图为这样的策略组织无限的数据处理流:每个线程从队列中提取节点进行处理,在处理之后进行处理—可能会出现一些新的处理节点—所以线程必须将它们放入队列中。但我不必对每个节点进行多次处理。节点是不可变的实体 据我所知,我必须使用队列和集合的一些线程安全实现(对于已经访问过的实例) 我试图避免使用同步方法。因此,我对该流程的实现:

简而言之:我想以并行方式处理带有循环引用的大型图。而且我也无法访问完整的图形,我必须在其中爬行。我想组织有效的队列来做到这一点。我很感兴趣,有什么最佳实践可以做到这一点吗

我试图为这样的策略组织无限的数据处理流:每个线程从队列中提取节点进行处理,在处理之后进行处理—可能会出现一些新的处理节点—所以线程必须将它们放入队列中。但我不必对每个节点进行多次处理。节点是不可变的实体

据我所知,我必须使用队列和集合的一些线程安全实现(对于已经访问过的实例)

我试图避免使用同步方法。因此,我对该流程的实现:

  • 当线程向队列中添加节点时,它会检查每个节点:如果访问的节点集包含此节点,则线程不会将其添加到队列中 排队。但这还不是全部

  • 当线程从队列中获取节点时,它会检查是否设置了已访问的节点 包含此节点。如果包含,则线程接受另一个 从队列中获取节点,直到获取节点,该节点尚未 已经处理过了。找到未处理的节点后-线程也添加 将其添加到已访问的节点集

  • 我尝试使用LinkedBlockingQueue和ConcurrentHashMap(作为一个集合)。我使用了ConcurrentHashMap,因为它包含方法putIfAbsent(key,value)——据我所知,这在原子上很有帮助:检查map是否包含key,如果不包含key,则添加它

    以下是所述算法的实现:

    public class ParallelDataQueue {
    
       private LinkedBlockingQueue<String> dataToProcess = new LinkedBlockingQueue<String>();
       // using map as a set
       private ConcurrentHashMap<String, Object> processedData = new ConcurrentHashMap<String, Object>( 1000000 );
       private final Object value = new Object();
    
       public String getNextDataInstance() {
        while ( true ) {
            try {
                String data = this.dataToProcess.take();
                Boolean dataIsAlreadyProcessed = ( this.processedData.putIfAbsent( data, this.value ) != null );
                if ( dataIsAlreadyProcessed ) {
                    continue;
                } else {
                    return data;
                }
            } catch ( InterruptedException e ) {
                e.printStackTrace();
            }
          }
        }
    
        public void addData( Collection<String> data ) {
        for ( String d : data ) {
            if ( !this.processedData.containsKey( d ) ) {
                try {
                    this.dataToProcess.put( d );
                } catch ( InterruptedException e ) {
                    e.printStackTrace();
                }
            }
           }
         }
    
    }
    
    公共类并行数据队列{
    私有LinkedBlockingQueue dataToProcess=新LinkedBlockingQueue();
    //使用地图作为集合
    私有ConcurrentHashMap processedData=新ConcurrentHashMap(1000000);
    私有最终对象值=新对象();
    公共字符串getNextDataInstance(){
    while(true){
    试一试{
    字符串数据=this.dataToProcess.take();
    布尔值dataIsAlreadyProcessed=(this.processedData.putIfAbsent(data,this.value)!=null);
    如果(数据isalreadyprocessed){
    继续;
    }否则{
    返回数据;
    }
    }捕捉(中断异常e){
    e、 printStackTrace();
    }
    }
    }
    公共数据(收集数据){
    for(字符串d:数据){
    如果(!this.processedData.containsKey(d)){
    试一试{
    this.dataToProcess.put(d);
    }捕捉(中断异常e){
    e、 printStackTrace();
    }
    }
    }
    }
    }
    
    所以我的问题是,当前的实现是否避免了对可重复节点的处理。也许还有更优雅的解决方案

    谢谢

    p.S.


    我理解,这样的实现并不能避免队列中节点的重复出现。但对我来说,这并不重要——我所需要的只是避免对每个节点进行多次处理。

    您当前的实现无法避免重复的数据实例。假设“线程A”检查并发映射中是否存在数据,并发现数据不存在,所以它将报告数据不存在。但就在执行if after putIfAbsent行之前,“线程A”被挂起。此时,另一个威胁“线程B”,计划由cpu执行,并检查同一数据元素的存在,发现它不存在,并报告为不存在,并将其添加到队列中。当线程A被重新调度时,它将从if行继续,并再次将其添加到队列中。

    是。使用
    ConcurrentLinkedQueue
    ()

    当线程向队列添加数据时,它会检查每个数据实例:如果集合包含此数据的实例,则线程不会将其添加到队列。但这还不是全部


    不是线程安全的方法,除非基础集合是线程安全的。(这意味着它在内部是同步的)但是检查是没有意义的,因为它已经是线程安全的了。

    如果你需要以多线程的方式处理数据,你可能根本不需要集合。你没有想过使用Executors框架吗

    public static void main(String[] args) throws InterruptedException {
        ExecutorService exec = Executors.newFixedThreadPool(100);
        while (true) { // provide data ininitely
            for (int i = 0; i < 1000; i++)
                exec.execute(new DataProcessor(UUID.randomUUID(), exec));
            Thread.sleep(10000); // wait a bit, then continue;
        }
    }
    
    static class DataProcessor implements Runnable {
        Object data;
        ExecutorService exec;
        public DataProcessor(Object data, ExecutorService exec) {
            this.data = data;
            this.exec = exec;
        }
        @Override
        public void run() {
            System.out.println(data); // process data
            if (new Random().nextInt(100) < 50) // add new data piece for execution if needed
                exec.execute(new DataProcessor(UUID.randomUUID(), exec));
        }
    
    }
    
    publicstaticvoidmain(String[]args)抛出InterruptedException{
    ExecutorService exec=Executors.newFixedThreadPool(100);
    while(true){//提供不完整的数据
    对于(int i=0;i<1000;i++)
    exec.execute(新的数据处理器(UUID.randomuid(),exec));
    Thread.sleep(10000);//稍等,然后继续;
    }
    }
    静态类DataProcessor实现可运行{
    对象数据;
    服务执行人;
    公共数据处理器(对象数据,ExecutorService exec){
    这个数据=数据;
    this.exec=exec;
    }
    @凌驾
    公开募捐{
    System.out.println(数据);//进程数据
    if(new Random().nextInt(100)<50)//如果需要,添加新的数据块以执行
    exec.execute(新的数据处理器(UUID.randomuid(),exec));
    }
    }
    
    我理解,这样的实现并不能避免队列中出现重复的数据。但对我来说,这并不重要——我所需要的只是避免多次处理每个数据实例。方法getNextDataInstance()不会返回已处理的数据。还是我错了?那应该没问题。HashMap是检测集合中是否存在项的最快方法之一。请描述一下ConcurrentLinkedQueue在这种情况下如何帮助我。是的,当然我使用的是执行器,但我也需要避免多次处理相同的数据。“相同的数据”是什么意思?是data1.equals(data2)还是data1==data2?无论如何,在这两种情况下,我担心在数据处理之外的设计会有问题。因为(当然,IMHO)跟踪数据是数据提供商的责任。或者,您可能不需要在中处理一段数据