蚂蚁金服笔试题

  • 题目一:
    提供一个懒汉模式的单实例类实现。
    要求:
    1.考虑线程安全。
    2.提供测试代码,测试线程安全性。
public class Singleton {
    public Singleton() {}
    /**
     * 内部静态类实现单例
     */
    private static class SingletonHolder{
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance(){
        return SingletonHolder.INSTANCE;
    }

    public static void main(String[] args) {
        //测试代码,验证50个线程去获取单例是不是一个实例
        for (int i = 0; i < 50; i++) {
            new Thread(() -> System.out.println(Singleton.getInstance().hashCode())).start();
        }
    }
}
  • 题目二
    1.设计含最小函数min()、pop()、push()的栈AntMinStack,存储数据元素为int
    2.AntMinStack中数据存储使用Stack结构
    要求:
    1.AntMinStack实现测试,满足栈特性
    2.要求min、push、pop、的时间复杂度都是O(1)
public class AntMinStack {

    Stack<Integer> stack; //存储值
    Stack<Integer> min;//存储最小值

    public AntMinStack(){
        stack = new Stack<>();
        min = new Stack<>();
    }

    public void push(int data){
        stack.push(data);
        if (min.isEmpty() || data <= min.peek()){
            min.push(data);
        }
    }
    public int pop() throws Exception{
        if (stack.isEmpty()){
            throw new Exception("EmptyStackException");
        }
        if (stack.peek() == min.peek()){
            min.pop();
        }
        return stack.pop();
    }
    public int min() throws Exception{
        if (min.isEmpty()){
            throw new Exception("EmptyStackException");
        }
        return min.peek();
    }

    public static void main(String[] args) throws Exception{
        AntMinStack antMinStack = new AntMinStack();
        for (int i = 20; i >= 0; i--) {
            antMinStack.push(i);
            System.out.println("入栈:"+i+",最小值为:"+antMinStack.min());
        }
        for (int i = 0; i < 19; i++) {
            System.out.println("出栈:"+antMinStack.pop()+"最小值为:"+antMinStack.min());
        }
    }
}
  • 题目三
    假设本地有一个文件夹,文件夹下面有若干文件(文件数大于50小于100),文件的存储格式是文本格式(后缀名是.txt),文件的大小每个文件不会超过100k
    文件格式如下:
    2000102,100,98.32000103,101,73.32000104,102,98.32000105,100,101.32000106,101,45.3……
    文件格式说明:文件每行都由三列构成,第一列是一个id,第二列是分组groupId, 第三列是指标quota。
    id的数据类型是String, groupId的数据类型String, quota的数据类型float。
    功能要求:1.把所有文件里面的内容按照分组进行排序,输出所有文件按照分组升序排序之后,每个分组下面的最小指标值。比如上面的数据输出结果为:100,2000102,98.3101,2000106,45.3102,2000104,98.3
    非功能要求:
    1.文件读取要有线程池来执行,线程池的大小固定为10,文件内容需要存储到指定的内容数据结构当中
    2.查找要求有独立线程来执行,直接消费读取线程池产生的内存数据结构。
    3.文件读取和排序要求并发作业,文件读取只要产生了数据,就可以把数据交给排序线程进行消费,计算最小值。
    代码要求
    1.重上面的要求语意里面抽象出合适的设计模式。
    2.需要考虑多线程的并发控制,同步机制。
    3.代码实现只能用JDK1.6或者1.8自带的工具类
/**  
 *     
 * 生产者线程
 * Author: Administrator   Date: 2018年8月28日  
 *       
 */
public class Producer implements Runnable{

    private LinkedBlockingQueue<DataItem> queue;
    private File file;
    private CountDownLatch countDownLatch;
    public Producer(LinkedBlockingQueue<DataItem> queue,File file,CountDownLatch countDownLatch) {
        this.queue = queue;
        this.file = file;
        this.countDownLatch = countDownLatch;
    }
    @Override
    public void run() {
        try {
            InputStreamReader read = new InputStreamReader(new FileInputStream(file));
            BufferedReader br=new BufferedReader(read);
            String line="";
            String[] arrs=null;
            while ((line=br.readLine())!=null) {
                if (line.equals("")) {
                    continue;
                }
                arrs=line.split(",");
                DataItem dataItem = new DataItem();
                dataItem.setId(arrs[0]);
                dataItem.setGroupId(arrs[1]);
                dataItem.setQuota(new Float(arrs[2]));
                queue.add(dataItem);
            }
            br.close();
            read.close();
            countDownLatch.countDown();
        } catch (Exception e) {
            e.printStackTrace();
        }   

    }

}
/**  
 *     
 * 消费者线程
 * Author: Administrator   Date: 2018年8月28日  
 *       
 */
public class Consumer implements Runnable{

    private LinkedBlockingQueue<DataItem> queue;
    private TreeMap<String, DataItem> treeMap;
    private CountDownLatch countDownLatch;
    public Consumer(LinkedBlockingQueue<DataItem> queue,TreeMap<String, DataItem> treeMap,CountDownLatch countDownLatch) {
        this.queue = queue;
        this.treeMap = treeMap;
        this.countDownLatch = countDownLatch;
    }
    @Override
    public void run() {
        try {
            while(true){
                if (!queue.isEmpty()) {
                    DataItem dataItem = queue.take();
                    DataItem mydataItem = treeMap.get(dataItem.getGroupId());
                    if (mydataItem == null) {
                        treeMap.put(dataItem.getGroupId(), dataItem);
                    }else{
                        if (dataItem.getQuota() < mydataItem.getQuota()) {
                            treeMap.put(dataItem.getGroupId(), dataItem);
                        }
                    }
                }else{
                    if(countDownLatch.getCount() <= 1){
                        countDownLatch.countDown();
                        break;
                    }
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}
/**  
 *     
 * 数据仓库
 * Author: Administrator   Date: 2018年8月29日  
 *       
 */
public class DataWareHouse {

    private static final int THREAD_POOL_SIZE = 10;
    private LinkedBlockingQueue<DataItem> queue;//缓存生产者线程从文件读取的数据
    private TreeMap<String, DataItem> treeMap;//存储消费者线程处理后的数据(排序、获取同组指标最小的数据)
    private ExecutorService threadPool;//线程池
    public DataWareHouse() {
        queue = new LinkedBlockingQueue<>();
        treeMap = new TreeMap<>(new Comparator<String>() {

            @Override
            public int compare(String o1, String o2) {
                return Long.valueOf(o1).compareTo(Long.valueOf(o2));
            }
        });
        threadPool = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
    }
    public LinkedBlockingQueue<DataItem> getQueue() {
        return queue;
    }
    public void setQueue(LinkedBlockingQueue<DataItem> queue) {
        this.queue = queue;
    }
    public TreeMap<String, DataItem> getTreeMap() {
        return treeMap;
    }
    public void setTreeMap(TreeMap<String, DataItem> treeMap) {
        this.treeMap = treeMap;
    }
    public ExecutorService getThreadPool() {
        return threadPool;
    }
    public void setThreadPool(ExecutorService threadPool) {
        this.threadPool = threadPool;
    }

}
/**  
 *     
 *  
 * Author: Administrator   Date: 2018年8月28日  
 *       
 */
public class DataItem {

    /**
     * id
     */
    private String id;
    /**
     * 分组
     */
    private String groupId;
    /**
     * 指标
     */
    private Float quota;

    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getGroupId() {
        return groupId;
    }
    public void setGroupId(String groupId) {
        this.groupId = groupId;
    }
    public Float getQuota() {
        return quota;
    }
    public void setQuota(Float quota) {
        this.quota = quota;
    }

}
public class Main {

    public static void main(String[] args) {
        String dirPath = "src/main/resources/files";
        File dirFile = new File(dirPath);
        File[] files = dirFile.listFiles();
        DataWareHouse dataWareHouse = new DataWareHouse();
        CountDownLatch countDownLatch = new CountDownLatch(files.length + 1);
        for(File file : files){
            Producer producer = new Producer(dataWareHouse.getQueue(), file,countDownLatch);
            //生产者线程使用线程池
            dataWareHouse.getThreadPool().execute(producer);
        }
        Consumer consumer = new Consumer(dataWareHouse.getQueue(), dataWareHouse.getTreeMap(),countDownLatch);
        //一个消费者线程消费
        new Thread(consumer).start();
        try {
            //生产者线程和消费者线程执行完成,关闭线程池,输出结果
            countDownLatch.await();
            dataWareHouse.getThreadPool().shutdownNow();
        } catch (Exception e) {
            e.printStackTrace();
        }
        Iterator<Entry<String, DataItem>> it = dataWareHouse.getTreeMap().entrySet().iterator();
        while(it.hasNext()) {
            Entry<String, DataItem> entry = it.next();
            DataItem dataItem = entry.getValue();
            System.out.println(dataItem.getGroupId() + "," + dataItem.getId()+","+dataItem.getQuota());
        }
    }
}
/**     
 * 创建测试数据
 * @author jiangpan 
 * @title CreateDataTest.java
 * @date 2018年8月29日 
 *     
 */
public class CreateDataTest {

    public static void main(String[] args) throws IOException {
        String path = "src/main/resources/files/";
        for (int i = 1; i < 100; i++) {
            File file = new File(path+i+".txt");
            if(!file.exists()){
                file.createNewFile();
            }
            FileWriter fileWriter = new FileWriter(file);
            BufferedWriter br = new BufferedWriter(fileWriter);
            for (int j = 0; j < 5000; j++) {
                br.write(getRandomData());
                br.newLine();
            }
            br.close();
            fileWriter.close();

        }
        System.out.println("success");
    }

    private static String getRandomData(){
        Integer id = (int)(Math.random() * 1000000) + 1000000;
        Integer groupId = (int)(Math.random() * 1000) + 100;
        Float quota = (int)(Math.random() * 1000)/10.0f+60;
        return id+","+groupId+","+quota;
    }
}
  • 4
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值