Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/373.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/9/ruby-on-rails-3/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_Md5_Hashcode_Modulo_Bucket - Fatal编程技术网

Java 如何将密钥分配到存储桶中,但确保每个存储桶至少有一个密钥?

Java 如何将密钥分配到存储桶中,但确保每个存储桶至少有一个密钥?,java,md5,hashcode,modulo,bucket,Java,Md5,Hashcode,Modulo,Bucket,我有一组“键”和“桶”,其中num_键>num_桶,但它们的数量级大致相同 举个具体的例子,一个“键”类似于一个任务,一个“桶”类似于一个线程。我希望将任务尽可能均匀地分配给线程,同时确保没有线程空闲 例如,我将有400个任务和200个线程: task1, task2, ..., task400 thread1, thread1, ... thread200 我想给线程分配一些统一的任务: thread1 -> task50, task394 thread2 -> task37,

我有一组“键”和“桶”,其中num_键>num_桶,但它们的数量级大致相同

举个具体的例子,一个“键”类似于一个任务,一个“桶”类似于一个线程。我希望将任务尽可能均匀地分配给线程,同时确保没有线程空闲

例如,我将有400个任务和200个线程:

task1, task2, ..., task400
thread1, thread1, ... thread200
我想给线程分配一些统一的任务:

thread1 -> task50, task394
thread2 -> task37, task250, task324
...
thread200 -> task20
这些是我编造的数字,但要清楚,对我来说更重要的是没有空闲线程;我不太在乎完美的分布

其他一些对我很重要的属性:

  • 对特定的桶没有偏见
  • 应始终将相同的密钥分配给相同的存储桶,而不考虑密钥的数量。如果bucket的数量改变了,那么赋值也可以改变(因此不需要某种一致的散列方案)
  • 分配应独立进行,无需外部协调
目前,我正试图用MD5实现这一点:

biginger numThreads=biginger.valueOf(200);//水桶
BigInteger currentThreadId=BigInteger.valueOf(1);
列出任务=getGlobalTasks();//钥匙
List myTasks=new ArrayList();
for(任务:任务){
BigInteger哈希=新的BigInteger(MessageDigest.getInstance(“MD5”).digest(task.getId());
biginger bucketId=hash.mod(numThreads);
if(currentThreadId.equals(bucketId)){
添加(任务);
}
}
我怀疑,如果键和桶的数量之间存在更大的差异,那么这种方法可以很好地工作。然而,在当前的方案中,大约35个线程处于空闲状态,因为它没有被分配任何密钥。我猜这是由于MD5散列分布的差异造成的

所以问题是,有没有办法重新构造代码以确保每个bucket/线程至少接收一个任务

注意:我实际上想做的是以一种灵活的方式分配(这意味着改变碎片的数量)。不过,这个问题的细节并不重要

下面是上面编译/运行的代码示例:

publicstaticvoidmain(字符串[]args)抛出NoSuchAlgorithmException{
biginger numBuckets=biginger.valueOf(20);//bucket
int numTasks=40;
列表任务=新建ArrayList();//键
对于(int i=0;i
以及输出:

Bucket: 0, Tasks: [2459, 2922]
Bucket: 1, Tasks: [21]
Bucket: 2, Tasks: [453]
Bucket: 3, Tasks: [494]
Bucket: 4, Tasks: null
Bucket: 5, Tasks: [1557, 2355]
Bucket: 6, Tasks: [4145, 1693]
Bucket: 7, Tasks: null
Bucket: 8, Tasks: null
Bucket: 9, Tasks: [1016, 4556]
Bucket: 10, Tasks: [3739]
Bucket: 11, Tasks: [4644, 3295]
Bucket: 12, Tasks: [2773, 3983, 2724]
Bucket: 13, Tasks: [1663]
Bucket: 14, Tasks: [2593, 2593, 1457, 3023, 1817, 4353, 4196]
Bucket: 15, Tasks: [2258, 802, 1530]
Bucket: 16, Tasks: [1882, 4765, 1969]
Bucket: 17, Tasks: [4882, 3030, 3429]
Bucket: 18, Tasks: [1666, 4377, 1714, 4109]
Bucket: 19, Tasks: [819, 7]

如您所见,有些存储桶是完全空的。

为什么不按顺序将任务填充到存储桶中?第
N
个任务将转到存储桶
N%numBuckets
。因此,他们将桶
1
填充到
X
,下一个新任务将再次从桶
1
开始填充。在我的特殊情况下,任务的数量有时会随时间而变化。我认为,如果任务数量发生变化,现有任务可能不会被分配到它们以前所在的bucket(假设任务按某种方式排序,如果任务被删除,那么所有后续任务都将被分配到bucket I-1)。我的线程在不同的机器上运行,因此无法访问共享内存。您有一个无法解决的需求。您说应该始终将这些密钥分配给同一个bucket,但当bucket空闲时,也应该将密钥分配给不同的bucket。要么让它们移动,要么不移动,哪一个?啊,我的意思是,我希望每个桶在原始分配中至少有一把钥匙。如果某个密钥被移除,导致包含该密钥的存储桶变为空,则无需将密钥迁移到该存储桶。如果删除的键太多以至于num_keys5的键,并且您不想更改它们时,如何将它们移动到另一个空的bucket?那是不可能的要求。你要么固定任务,要么改变任务。您必须选择:您是希望保留对其存储桶的原始密钥分配作为最终分配,还是希望根据情况(如空存储桶)将密钥分配给不同的存储桶(与原始分配不同)?这些要求相互冲突。