如何多线程解决这个问题?

时间:2011-05-16 17:52:30

标签: java multithreading concurrency

我想对分布式系统进行模拟,其中,我应该以分布式(并行,如果我可以!!)的方式研究信息(供应),例如我有以下类: / p>

public class Group{
public int identifier;
public int[] members;
public String name; 
public String[] supplies;
public int[] neighbors;}

有许多组,每个组都有一个名称,由一个成员,邻居和用品列表组成,每个成员都有一些信息,并列出可能包含相关信息和用品的其他组,等等。

1-我想研究用品,首先:在一个小组内,如果我找不到所需的供应,我应该在所有与该小组相邻的小组内进行搜索,我想要做到这一点使用多线程,我的意思是,如果搜索失败,我应该使用多个线程同时在所有其他邻居内进行搜索,每个线程都考虑一个邻居,如果我有10个邻居,则应创建10个线程....

2-现在,如果我想在几个小组的第一次开始重新搜索,我的意思是从3组或4组开始,每组都寻找不同的供应,或者相同...... 。  +一个调用搜索的组可以是另一个组的邻居...

所以,我的问题是如何使用线程实现这种情况?

PS。我有一台带有一个核心的单处理器的机器,我不关心执行时间(开销),我只想模拟这个问题...

感谢您的每一个回复和最好的问候。

3 个答案:

答案 0 :(得分:1)

由于您遇到了CPU绑定问题,因此使用的最佳线程数可能是您拥有的核心数。我会确保每个线程有大约100微秒的工作,或者你会发现你有更多的头脑而不是有用的工作。例如您可能会发现搜索10K节点大约有100个工作。如果您不小心,多线程应用程序可能比单线程应用程序慢很多倍。

所以我会找到一种方法来分割工作,这样你就可以为每个线程提供大约1K到100K的节点,并将你的并发性限制为你拥有的核心数。

答案 1 :(得分:1)

我无法理解第二个要求,但对于第一个要求,这是一种可行的方法。在此之前,从技术上讲,您的进程不是完全受CPU限制,它也是I / O绑定(网络)。因此,请不要认为使其多线程将提供您正在寻找的所需加速。我假设您的开发环境是单处理器和单核,但您的部署环境可能不是。

回到建议。我会创建一个GroupPool类,它有一个可以侦察信息的线程池。线程数可通过运行时配置参数进行配置。您可以创建一个工厂类,它从配置文件中读取此参数,并创建一个可运行对象池。

这些对象中的每一个都代表与相邻节点的一个连接。 [TODO]您没有提及是否要在供应商节点上进行递归,即如果您未在供应商节点中找到该信息,是否要搜索供应商,供应商的供应商等。如果是,您将有循环检测的问题。一旦这些线程对象侦察信息并找到它,它们就会更新工厂对象上的信号量(您可能希望将其移动到一个单独的对象,因为这将是一个更好的设计),并且还发送供应商ID(请参阅单独的对象确实有意义)

您可以拥有此修改后的信号量的监听器,并且一旦值发生更改,您就会知道您已找到您的信息并从该对象获取供应商ID。获得信息后,您可以向线程池发送通知,以便在您找到信息时关闭可运行对象。

根据您是否正在寻找二元答案(查找数据和任何供应商都可以),如果您想要递归,上述复杂性将会增加。

希望这有助于您尝试为您的问题设计结构。

答案 2 :(得分:1)

我认为在单CPU机器上多线程化没有任何性能优势。这是因为一次只能运行一个线程,并且线程之间会有切换时间,因此实际上可能需要更多时间才能找到具有所需资源的组。

就个人而言,我只是遍历第一组的邻居并检查它们的资源。然后,如果找不到资源,我会调用每个子组的搜索,传入已经检查过的组列表,这样就可以跳过已经检查过的组。类似的东西:

public Group searchForGroupWithResource(Resource resource){
    List<Group> groupsToCheck = new ArrayList<Group>();
    groupsToCheck.add(this);
    int currentIndex = 0;
    while(currentIndex < groupsToCheck.size()){
        Group currentGroup = groupsToCheck.get(currentIndex);
        if(currentGroup.hasResource(resource)){
            return currentGroup;
        }
        groupsToCheck.addAll(currentGroup.getNeighbors(groupsToCheck));
        currentIndex++;
    }
    return null;
}

public List<Group> getNeighbors(List<Group> excludeGroups){
    //Get non-excluded neighbors
    List<Group> returnNeighbors = new ArrayList<Group>();
    for(Group neighbor : neighbors){
        boolean includeGroup = true;
        for(Group excludeGroup : excludeGroups){
            if(excludeGroup.equals(neighbor)){
                includeGroup = false;
                break;
            }
        }
        if(includeGroup){
            returnNeighbors.add(neighbor);
        }
    }
    return returnNeighbors;
}

注意:如果您仍然决定使用多线程,我建议使用一个公共对象来存储所有线程都可以访问的搜索信息。这将指定已检查的组(因此您不会检查同一组两次)以及是否找到所需的耗材(因此您可以停止检查资源)。