繁体   English   中英

Java并发-将数据传递给其他等待线程

[英]Java concurrency - pass data to other waiting thread

我有两个组成部分:

  • 可以在其上调用add(Data)的管理器。 这会将一些数据添加到管理器。
  • 客户端,可以在管理器上调用retrieve(predicate) 返回与给定谓词匹配的Data对象的列表。 如果没有此类数据,则retrieve将继续等待。

由于客户端对每个新对象都不感兴趣,因此无法在此处使用典型的阻塞优先级队列。 只有那些由谓词中定义的他的要求所允许的人才对他有用。

如何用Java实现呢? 我能得到它工作x.notifyAll()在每次通话后调用add(Data)的经理,和x.wait()retrieve(predicates)方法。 我想知道java.concurrent包是否具有可以用于此问题的更高级功能。

以下是一些可能会给您带来想法的概述。 为了简单起见,我将假定predicatesdata是字符串。

如您所说,您不提前知道predicates ,因此我将尝试根据新传入的谓词动态更新和缓存。

经理

public class Manager(){
    private Map<String, Set<String>> jobs = new HashMap<>():
    private Set<String> knownPredicates = new HasSet();
    private final static String GENERAL = "GENERAL_DATA";

    public void addJob(String data){
        Set<String> matchingPredicates = getMatchingPredicates(data);
        if(matchingPredicates.isEmpty()){
            updateJobs(GENERAL, data);
        } else {
            for(String predicate: matchingPredicates){
                updateJobs(GENERAL, data);
            }
        }

        synchronized(this){
            notifyAll();
        }
    }

    private Set<String> getMatchingPredicates(String data){
        Set<String> matchingPredicates = new HashSet<>();
        for(String knownPredicate: knownPredicates){
            // Check if the data matched the predicate. If so add it to the list
        }
        return matchingPredicates;
    }

    private void updateJobs(String predicate, String data){
        Set<String> dataList;
        if(jobs.containsKey(predicate)){
            dataList = jobs.get(predicate);
        } else {
            dataList = new HashSet<>();
        }
        dataList.add(data);
        jobs.put(predicate, dataList);
    }

    public synchronized List<String> retrieve(String predicate){
        Set<String> jobsToReturn;
        knownPredicates.add(predicate);
        if(jobs.containsKey(predicate)){
            jobsToReturn = jobs.remove(predicate); 
        }

        for(String unknownData: jobs.get()){
            //Check if unknownData matches the new predicate if it does add it to jobsToReturn
        }

        cleanupData(jobsToReturn);
        return jobsToReturn;
    }

    //Removes data that may match more than one predicate
    private static void cleanupData(Set<String> dataSet){
        for(String data: dataSet){
            for(Set <String> predicateSet: jobs.values()){
                predicateSet.remove(data);
            }
        }
    }
}

客户

public class Client() implements Runnable{
    private Manager managerRef;
    public Client(Manager m){
        managerRef = m;
    }

    public void run() {
        while(true){
            String predicate = //Get the predicate somehow
            Set<String> workToDo = managerRef.retrieve(predicate)
            if(workToDo.isEmpty()){
                synchornized(managerRef){
                    managerRef.wait();
                } 
            } else {
                //Do something
            }
        }
    }
}

上面只是一个骨架。 您将必须解决一些有关清除已知谓词等的问题。

您可能需要考虑使用以下行为来实现基于谓词的缓存:

  • 如果从未调用过'retrieve(predicate)'方法并且执行了'add(Data)'方法, 'add(Data)'一个新的Data对象简单地添加到管理器中,并且缓存保持为空。
  • 如果'retrieve(predicate)'方法,则客户端将在高速缓存中检查所请求的谓词,以便检索对相应Data对象的引用。 如果高速缓存为空或找不到匹配项,则系统针对管理器中的所有数据对象在指定谓词上进行搜索,并更新高速缓存。 为了提高性能,如果找不到匹配项,请在缓存中将其标记出来,以便更快地返回对同一谓词的后续查询。
  • 如果调用了'add(Data)'方法并且缓存不为空,则将对要添加的Data对象进行扫描,以查找缓存中已经存在的所有谓词,并且匹配对象将通过引用与缓存中的相应谓词相关联。

请注意,任何缓存机制在开始时都会比较慢,但随着更多对象填满缓存,它会有所改善。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM