10个人同时从10万条数据中取一条数据,要求取到的数据不相同!
1.有两种方法:
10个人按顺序取。当这个人取得时候,其他人不能取(取完设置一个标志位)。
2.同时取,取完再比较。转成hashSet。size不等于10就说明有重复。然后再取一遍。直到不重复。
推荐第一种、
题主的意思应该是,10个人,随机读取10W条数据,但是必须保证每个人读取的数据是不一样的。比如说A去读取第99条数据这个时候B也读到了第99条数据,这个时候B就必须重新选择一条数据去读取。
我觉得可以在读数据之前先确定读取的是哪条数据,并且把相应的数据行放入一个concurrentHashMap
中,下一次读取的时候先判断读取的数据行在Map中是否存在就好了。
我的想法是,N个人从M条(很大)数据中取出数据,要求取到的数据不相同,那么有两个点:一个是存放数据的容器,第二个是如何判重复。
为了高并发读取,我考虑是使用一个无锁的数组保存数据,使用一个Atomic指针head控制对数组的并发访问,一个线程需要CAS操作head来获取一个数据,如果判断重复获取过了,就取下一个,抢到资源后Thread.yield()防止有的线程持续执行抢占大量资源(旱的旱死,涝的涝死)。判重可以使用ConcurrentHashMap。写了一个模拟程序如下:
package juc;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.IntStream;
public class QueryMillion {
private final static int N = 10;
private final static int SIZE = 100000;
private final static Data[] dataset;
private final static Map<Data, Boolean> map = new ConcurrentHashMap<>();
private final static AtomicInteger head = new AtomicInteger(0);
static {
Data[] array = new Data[SIZE];
Random random = ThreadLocalRandom.current();
for(int i = 0; i< SIZE; i++){
array[i] = new Data(random.nextInt(SIZE));
}
dataset = array;
}
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(N);
long startMils = System.currentTimeMillis();
IntStream.range(0, N).forEach(i->{
new Thread(()->{
int p;
while((p=head.getAndIncrement())<SIZE) {
Data userData = dataset[p];
if(!map.containsKey(userData)) {
map.put(userData, true);
System.out.println(Thread.currentThread().getName() + " get " + userData.hashCode());
Thread.yield();
}
}
latch.countDown();
},"user-"+i).start();
});
latch.await();
long endMils = System.currentTimeMillis();
System.out.printf("Total cost: %dms\n", (endMils-startMils));
}
private static class Data{
private Integer id;
public Data(int id){
this.id = id;
}
@Override
public int hashCode(){
return id;
}
@Override
public boolean equals(Object o){
if(o.getClass() != this.getClass()) return false;
return o.hashCode() == this.hashCode();
}
}
}
15 回答8.4k 阅读
8 回答6.2k 阅读
1 回答4.1k 阅读✓ 已解决
3 回答2.2k 阅读✓ 已解决
2 回答3.1k 阅读
2 回答3.8k 阅读
3 回答1.7k 阅读✓ 已解决
把10万个数加上10把区域锁,每个人就限制在该区域拿,就不会重复了,java中有实现的类