关于java并发的面试题

10个人同时从10万条数据中取一条数据,要求取到的数据不相同!

阅读 7.4k
8 个回答

把10万个数加上10把区域锁,每个人就限制在该区域拿,就不会重复了,java中有实现的类

1.有两种方法:
10个人按顺序取。当这个人取得时候,其他人不能取(取完设置一个标志位)。
2.同时取,取完再比较。转成hashSet。size不等于10就说明有重复。然后再取一遍。直到不重复。
推荐第一种、

可以试试使用java的并发集合,比如concurrentHashMap等。

如果描述的就是全部的要求的话,第X个人取第X条数据不就好了?

BlockingQueue.take()

题主的意思应该是,10个人,随机读取10W条数据,但是必须保证每个人读取的数据是不一样的。比如说A去读取第99条数据这个时候B也读到了第99条数据,这个时候B就必须重新选择一条数据去读取。

我觉得可以在读数据之前先确定读取的是哪条数据,并且把相应的数据行放入一个concurrentHashMap中,下一次读取的时候先判断读取的数据行在Map中是否存在就好了。

使用BlockingQueue

我的想法是,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();
        }
    }
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题