我想对分布式系统进行模拟,其中,我应该以分布式(并行,如果我可以!!)的方式研究信息(供应),例如我有以下类: / 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。我有一台带有一个核心的单处理器的机器,我不关心执行时间(开销),我只想模拟这个问题...
感谢您的每一个回复和最好的问候。
答案 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;
}
注意:如果您仍然决定使用多线程,我建议使用一个公共对象来存储所有线程都可以访问的搜索信息。这将指定已检查的组(因此您不会检查同一组两次)以及是否找到所需的耗材(因此您可以停止检查资源)。