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

时间:2016-03-31 08:48:32

标签: java concurrency

我有两个组成部分:

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

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

如何在Java中实现?在每次调用管理器中的x.notifyAll()add(Data)方法中的x.wait()后,我都可以使用retrieve(predicates)调用。我想知道java.concurrent包是否具有更高级别的功能,可用于此问题。

2 个答案:

答案 0 :(得分:1)

以下是可能会给您一个想法的概要。为简单起见,我假设by-namepredicates是字符串。

如你所说,你提前不知道你的data所以我会尝试根据新的传入谓词动态更新和缓存。

<强>管理器

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);
            }
        }
    }
}

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

答案 1 :(得分:-1)

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

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

请注意,作为任何缓存机制,它在开始时会较慢,但会随着更多对象填满缓存而改进。