JAVA面試題,java試題

來源:互聯網
上載者:User

JAVA面試題,java試題

在這裡我將收錄我面試過程中遇到的一些好玩的面試題目

第一個面試題:ABC問題,有三個線程,工作的內容分別是列印出“A”“B”“C”,需要做的就是讓他們順序的輸出ABC  例如:ABCABCABCABC

思路一:我覺得這個功能是需要封裝的,而且能夠做到,無論多少個線程都能夠順序列印出來,並且基本上不需要改任何代碼。我的思路是首先封裝一個工作的單元為Node,主要的工作就是列印和競爭鎖並且記錄加入工作的索引,然後還有一個ConcurrentHashMap儲存工作狀態。如果全部工作完了之後,由最後一個工作單元重新整理狀態。下面是實現的代碼:

package com.hotusm.concurrent.test;import java.util.Map;import java.util.TreeMap;import java.util.concurrent.TimeUnit;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;/** * Created by luqibao on 2016/12/30. */public class ABCSample {    private static ReentrantLock lock=new ReentrantLock();    private static volatile TreeMap<Integer,Node> indexs=new TreeMap<>();    public static void main(String[] args){        ReentrantLock lock=new ReentrantLock();        TreeMap<Integer,Node> indexs=new TreeMap<>();        Node node1=new Node("A",lock,indexs,0);        Node node2=new Node("B",lock,indexs,1);        Node node3= new Node("C",lock,indexs,2);        indexs.put(0,node1);        indexs.put(1,node2);        indexs.put(2,node3);        node1.beforeWork();        node2.beforeWork();        node3.beforeWork();        try{            TimeUnit.SECONDS.sleep(3);        }catch (Exception e){            e.printStackTrace();        }        node1.start();        node2.start();        node3.start();        synchronized (ABCSample.class){            try{                ABCSample.class.wait();            }catch (Exception e){                e.printStackTrace();            }        }    }    private static class WorkQueue{        private Node tail;        private Node head;    }    private static class Node extends Thread{        private static volatile boolean isRefresh=false;        private volatile Map<Integer,Node> maps;        private volatile boolean isWorked=false;        private final int index; //索引        private String message;        private volatile Lock readLock;        private boolean isLast=false;        public Node(String message,Lock lock,Map<Integer,Node> maps,int index){            this.message=message;            this.readLock=lock;            this.maps=maps;            this.index=index;        }        public int getIndex() {            return index;        }        public void beforeWork(){            readLock.lock();            try{                if(index==maps.size()-1){                    isLast=true;                }else{                    isLast=false;                }            }finally {                readLock.unlock();            }        }        @Override        public void run() {            while (true){                readLock.lock();                if(isRefresh){continue;}                try{                    if(this.index==0&&!this.isWorked){                        System.out.print(this.message);                        this.isWorked=true;                    }else if(index!=0){                        Node node= maps.get(index-1);                        if(!node.isWorked){                            System.out.print(node.message);                            node.isWorked=true;                        }else{                            if(!this.isWorked){                                System.out.print(this.message);                                this.isWorked=true;                            }else if(this.isWorked&&this.isLast){                                refresh();                            }                        }                    }                }catch (Exception e){                    Thread.currentThread().interrupt();                    e.printStackTrace();                }finally {                    readLock.unlock();                }                try{                    TimeUnit.SECONDS.sleep(1);                }catch (Exception e){                    e.printStackTrace();                }            }        }        private void refresh(){            isRefresh=true;            for(Map.Entry<Integer,Node> map:maps.entrySet()){                map.getValue().isWorked=false;            }            isRefresh=false;        }    }}

其實上面還有很多封裝的地方,註冊可以封裝成方法,前置工作也是,可以用一個volatile修飾的boolean來標記,同理啟動也是一樣的,如果能夠的話,最好能做到,使用的時候只需要調用一個register(msg) 和start()就可以了

思路二:因為這是一個環形連結結構,所以我們可以通知將鎖從head開始一直往後讓其他擷取一遍,下面代碼:

package com.hotusm.concurrent.test;import sun.misc.Unsafe;import java.lang.reflect.Field;import java.util.concurrent.CountDownLatch;/** * Created by luqibao on 2017/1/3. */public class ABCSample2 {    public static void main(String[] args){       WorkQueue queue= new WorkQueue();       queue.addWork("A");       queue.addWork("B");       queue.addWork("C");       queue.addWork("D");       queue.addWork("E");       queue.startWork();        synchronized (ABCSample2.class){            try{                ABCSample2.class.wait();            }catch (Exception e){                e.printStackTrace();            }        }    }    private static class WorkQueue{        private Node head;        private Node tail;        private int num=0;        private static final Unsafe unsafe = getUnsafe();        private static final long tailOffset;        private static final long headOffset;        static {            try {                // 擷取當前欄位的記憶體位置  後來替換的地方需要使用                headOffset = unsafe.objectFieldOffset                        (WorkQueue.class.getDeclaredField("head"));                tailOffset = unsafe.objectFieldOffset                        (WorkQueue.class.getDeclaredField("tail"));            } catch (Exception ex) { throw new Error(ex); }        }        private static Unsafe getUnsafe() {            try {                Field singleoneInstanceField = Unsafe.class.getDeclaredField("theUnsafe");                singleoneInstanceField.setAccessible(true);                return (Unsafe) singleoneInstanceField.get(null);        } catch (Exception e) {                throw new RuntimeException(e);            }        }        protected void push(Node node){            for (;;) {                Node t = tail;                if (t == null) {                    if (compareAndSetHead(node))                        num++;                    tail = head;                    break;                } else {                    if (compareAndSetTail(t, node)) {                        num++;                        t.next = node;                        break;                    }                }            }        }        /**         *加入工作的順序就是列印的順序         * @param message  列印的資訊         */       public void addWork(String message){            Node node=new Node(message);            push(node);        }        /**         * 開始進行工作         */        public void startWork(){            Node.head=this.head;            Node.tail=tail;            Node.latch=new CountDownLatch(num);            Node.currentWork=head;            for (Node node=head;node!=null;node=node.next){                node.start();                Node.latch.countDown();            }        }        public boolean compareAndSetTail(Node expect,Node newValue){            return unsafe.compareAndSwapObject(this,tailOffset,expect,newValue);        }        public boolean compareAndSetHead(Node expect){            return unsafe.compareAndSwapObject(this,headOffset,null,expect);        }    }    private static class Node extends Thread{        private static volatile Node currentWork;        private static volatile Node head;        private static volatile Node tail;        private static volatile CountDownLatch latch;        private String message;        private Node next;        public Node(String message) {            this.message = message;        }        @Override        public void run() {            try {                latch.await();            }catch (Exception e){                e.printStackTrace();            }            for(;;){                if(currentWork==this){                    if(!"".equals(message)){                        System.out.print(message);                    }                    if(this==tail){                        currentWork=head;                    }else{                        currentWork=this.next;                    }                }            }        }    }}

總的來說,我還是比較喜歡後面這種的,但是還是需要最佳化,比如在啟動之後就不能夠添加工作了,驗證工作不能重複等等。

第二個面試題:

具體題目如下,-         Java開發-         功能要求:o   網路爬蟲,可以使用少量的3方庫,但是最好能夠用自己寫的代碼o   加分點:使用多線程,注意同步和鎖o   將豆瓣(book.douban.com)裡的關於“互連網,編程,演算法”方面的書籍資料抓下來,並且顯示評分最高的前100本資料(要求評價人數超過2000,不足2000的就提取前100)o   代碼和爬下的結果(excel檔案)一併放在github裡,連結發給你們,再轉給我。

這個面試題是一家500強的外企的題目,因為之前一直沒有接觸過爬蟲方面,所以覺得比較有意思,代碼在我們的github上面:https://github.com/Housum/crawl.git。

因為當時時間比較緊(白天在項目),本來是想自己寫網路和解析的,但是沒時間,所以用的都是第三方的,反而覺得除了鎖,其他的都是第三方架構的東西。面試官評價還行。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.