1. 程式人生 > >集合類 Java中的集合類解析和一些有深入的面試題

集合類 Java中的集合類解析和一些有深入的面試題

第一題:

      現有的程式程式碼模擬產生了16個日誌物件,並且需要執行16秒才能列印完這些日誌,請在程式中增加4個執行緒去呼叫parseLog()方法來分頭列印

      這16個日誌物件,程式只需要執行4秒即可列印完這些日誌物件。

原始程式碼:

  1. publicclass Test {  
  2.         publicstaticvoid main(String[] args){  
  3.             System.out.println("begin:"+(System.currentTimeMillis()/1000));  
  4.             /*模擬處理16行日誌,下面的程式碼產生了16個日誌物件,當前程式碼需要執行16秒才能列印完這些日誌。
     
  5.             修改程式程式碼,開四個執行緒讓這16個物件在4秒鐘打完。 
  6.             */
  7.             for(int i=0;i<16;i++){  //這行程式碼不能改動
  8.                 final String log = ""+(i+1);   //這行程式碼不能改動
  9.                 {  
  10.                         Test.parseLog(log);  
  11.                 }  
  12.             }  
  13.         }  
  14.         //parseLog方法內部的程式碼不能改動
  15.         publicstaticvoid parseLog(String log){  
  16.             System.out.println(log+":"+(System.currentTimeMillis()/1000));  
  17.             try {  
  18.                 Thread.sleep(1000);  
  19.             } catch (InterruptedException e) {  
  20.                 e.printStackTrace();  
  21.             }         
  22.         }     
  23.     }  

實現:通過阻塞佇列實現執行緒間的通訊

  1. import java.util.concurrent.ArrayBlockingQueue;  
  2. import java.util.concurrent.BlockingQueue;  
  3. //BlockingQueue
  4. publicclass Test {  
  5.     publicstaticvoid main(String[] args){  
  6.         //建立一個空間大小為16的阻塞佇列,空間大小可以任意,因為每次列印都要1秒,在此期間,
  7.         //4個執行緒足以不斷去從佇列中取資料,然後列印,即在1秒內列印4條日誌資訊
  8.         final BlockingQueue<String> queue = new ArrayBlockingQueue<String>(16);  
  9.         //開啟4個執行緒列印
  10.         for(int i=0;i<4;i++){  
  11.             new Thread(new Runnable(){  
  12.                 @Override
  13.                 publicvoid run() {  
  14.                     while(true){  
  15.                         try {  
  16.                             String log = queue.take();  //開始沒有資料,阻塞,一旦有其中一個執行緒就去取
  17.                                             //資料,即不再阻塞,就開始列印
  18.                             parseLog(log);  
  19.                         } catch (InterruptedException e) {  
  20.                             e.printStackTrace();  
  21.                         }  
  22.                     }  
  23.                 }  
  24.             }).start();  
  25.         }  
  26.                //列印秒數
  27.         System.out.println("begin:"+(System.currentTimeMillis()/1000));  
  28.         for(int i=0;i<16;i++){  //這行程式碼不能改動
  29.             final String log = ""+(i+1);//這行程式碼不能改動
  30.             {  
  31.                     try {  
  32.                         queue.put(log);     //向佇列中儲存資料
  33.                     } catch (InterruptedException e) {  
  34.                         e.printStackTrace();  
  35.                     }  
  36.                     //Test.parseLog(log);
  37.             }  
  38.         }  
  39.     }  
  40.     //parseLog方法內部的程式碼不能改動
  41.     publicstaticvoid parseLog(String log){  
  42.         System.out.println(log+":"+(System.currentTimeMillis()/1000));  
  43.         try {  
  44.             Thread.sleep(1000);     //模擬每條日誌列印需要1秒
  45.         } catch (InterruptedException e) {  
  46.             e.printStackTrace();  
  47.         }         
  48.     }  
  49. }  


 第二題:

         現成程式中的Test類中的程式碼在不斷地產生資料,然後交給TestDo.doSome()方法去處理,就好像生產者在不斷地產生資料,消費者在不斷消費資料。

        請將程式改造成有10個執行緒來消費生成者產生的資料,這些消費者都呼叫TestDo.doSome()方法去進行處理,故每個消費者都需要一秒才能處理完,程

        序應保證這些消費者執行緒依次有序地消費資料,只有上一個消費者消費完後,下一個消費者才能消費資料,下一個消費者是誰都可以,但要保證這些消

        費者執行緒拿到的資料是有順序的。

原始程式碼:

  1. publicclass Test {  
  2.         publicstaticvoid main(String[] args) {  
  3.             System.out.println("begin:"+(System.currentTimeMillis()/1000));  
  4.             for(int i=0;i<10;i++){  //這行不能改動
  5.                 String input = i+"";  //這行不能改動
  6.                 String output = TestDo.doSome(input);  
  7.                 System.out.println(Thread.currentThread().getName()+ ":" + output);  
  8.             }  
  9.         }  
  10.     }  
  11.     //不能改動此TestDo類
  12.     class TestDo {  
  13.         publicstatic String doSome(String input){  
  14.             try {  
  15.                 Thread.sleep(1000);  
  16.             } catch (InterruptedException e) {  
  17.                 e.printStackTrace();  
  18.             }  
  19.             String output = input + ":"+ (System.currentTimeMillis() / 1000);  
  20.             return output;  
  21.         }  
  22.     }  


在實現之前先介紹一個阻塞佇列:SynchronousQuene   

      一種阻塞佇列,其中每個插入操作必須等待另一個執行緒的對應移除操作 ,反之亦然。

      同步佇列沒有任何內部容量,甚至連一個佇列的容量都沒有。除非另一個執行緒試圖移除某個元素,否則也不能(使用任何方法)插入元素;

      也不能迭代佇列,因為其中沒有元素可用於迭代。

應用:

     它非常適合於傳遞性設計,在這種設計中,在一個執行緒中執行的物件要將某些資訊、事件或任務傳遞給在另一個執行緒中執行的物件,

      它就必須與該物件同步。 

程式碼實現:

  1. import java.util.concurrent.SynchronousQueue;  
  2. 相關推薦

    集合 Java集合解析一些深入試題

    第一題:       現有的程式程式碼模擬產生了16個日誌物件,並且需要執行16秒才能列印完這些日誌,請在程式中增加4個執行緒去呼叫parseLog()方法來分頭列印       這16個日誌物件,程式只需要執行4秒即可列印完這些日誌物件。 原始程式碼: pub

    Java併發(十二):CAS Unsafe Atomic 說一說Java的Unsafe 說一說Java的Unsafe JavaUnsafe詳解 Unsafe與CAS

    一、Unsafe Java無法直接訪問底層作業系統,而是通過本地(native)方法來訪問。不過儘管如此,JVM還是開了一個後門,JDK中有一個類Unsafe,它提供了硬體級別的原子操作。 這個類儘管裡面的方法都是public的,但是並沒有辦法使用它們,JDK API文件也沒有提供任何關於這個類的方法的解

    java的編譯期執行期什麼區別?

    編譯期和執行期進行的操作是不相同的,編譯器只是進行語法的分析,分析出來的錯誤也只是語法上的錯誤,而執行期在真正在分配記憶體。 編譯時是呼叫檢查你的源程式是否有語法錯誤,如果沒有就將其翻譯成位元組碼檔案

    iOS Block深層次總結一些經典的試題

    上面幾個是之前看書記錄的知識點,可以回顧下,下面用人話概括下自己的理解,方便以後參考,先記住一個概念,Block就是一個物件 OC Block—> C++轉換 1.最普通的轉換 int a = 100; int b = 2

    Java集合set、Listmap的遍歷方式

    Java中集合類的遍歷方式 Java中集合分為set、List和map。 1.set集合 set集合常用的有兩種遍歷方式: Set<String>  set = new HashSet<String>(); 第一種利用for迴圈: for(S

    java使用sax解析xml,以實體集合的方式接受xml解析的值

    1.先編寫要解析的xml檔案: <?xml version="1.0" encoding="utf-8"?> <class> <stu id="001"> <name>Allen</name> <sex&g

    Java集合容器初步了解

    equals treemap 輸入 strong 字符串數組 通過 system 結構 shm   容器(Collection)     數組是一種容器,集合也是一種容器     java編程中, 裝其他各種各樣的對象(引用類型)的一種東西, 叫容器     (圖書

    (轉)詳細解析Java抽象介面的區別

    原文地址:https://zhuanlan.zhihu.com/p/50989401 在Java語言中, abstract class 和interface 是支援抽象類定義的兩種機制。正是由於這兩種機制的存在,才賦予了Java強大的 面向物件能力。abstract class和interface之間在對於

    Java 集合型別包含ArrayList、LinkedList、HashMap等,下列描述正確的是(多選)?

    A.ArrayList與LinkedList都實現了List介面B.刪除元素時,ArrayList的表現更佳C.ArrayList的訪問速度比LinkedList快D.HashMap實現Map介面,允許任何型別的鍵和值物件,並且允許鍵和值都為null答案:ACD擴充套件:瞭解

    Java集合的內容總結

    package JavaSum; import java.util.LinkedHashMap; import java.util.Scanner; public class TestMap {         private LinkedHashMap<String,TestEmployee>

    詳細解析Java抽象介面的區別

      在abstract class方式中,Demo可以有自己的資料成員,也可以有非 abstract的成員方法,而在interface方式的實現中,Demo只能夠有靜態的不能被修改的資料成員(也就是必須是static final 的,不過在interface中一般不定義資料成員),所有的成員方法都是abstr

    JAVA集合說明及區別

    集合類說明及區別Collection ├List │├LinkedList │├ArrayList │└Vector │ └Stack └Set Map ├Hashtable ├HashMap └WeakHashMap Collection介面   Collection是最基本的集合介面,一個C

    Java抽象接口的區別

    pre data 區分 信息 展示 關於 面向 得出 lose 在Java語言中, abstract class 和interface 是支持抽象類定義的兩種機制。正是由於這兩種機制的存在,才賦予了Java強大的 面向對象能力。abstract class和interfac

    Java接口

    擁有 編程 指針 比較 抽象類 trac 屬於 ace code 類有兩種: 普通類 : 抽象類(abstract): 抽象類除了不能實例化對象之外,類的其它功能依然存在,成員變量、成員方法和構造方法的訪問方式和普通類一樣。 由於抽象類不能實例化對象,所以抽象類必須被繼承

    JAVA返回型使用泛型TObject什麽區別?

    some http cast one gpo aud pre 使用 安全 最近在讀jackson源碼的時候發現有段代碼返回類型寫的是<T> T,而我自己一般寫的是Object。上網搜了下這個語法糖,在stackoverflow上找到一個比較簡單易懂的解釋,搬運過

    c#的裏氏轉換Java強制型轉換在多態的應用

    readline color extends pre pri console AS 定義 spa 在c#中: 註意: 子類並沒有繼承父類的構造函數,而是會默認調用父類那個無參數的構造函數。 如果一個子類繼承了一個父類,那麽這個子類除了可以使用自己的成員外,還可以使用從父類

    java字符串其他數據型之間使用“+”號連接

    之間 一個 連接 數據 類型 style bsp 其他 pre int i1=100; int i2=2; System.out.println(i1+"*"+i2+"="+i1*i2);//100*2=200

    java抽象抽象方法到底什麽關系?請舉例說明!

    init 舉例 web nds ike anti 聲明 use dont 抽象類和抽象方法什麽關系?抽象類中可能有抽象方法,也可能沒有抽象方法。(視頻下載) (全部書籍)那位說,就跟沒說一樣,那抽象類和抽象方法都叫抽象,他們必定有關系,那關系是什麽呢?如果一個類中有抽象方法

    java物件

    類 類在客觀世界裡是不存在的,是描寫物件的資訊 類是模子,確定物件將會擁有的特徵(屬性)和行為(方法)  類的特點 類是物件的型別 具有相同屬性和方法的一組物件的集合 屬性(特徵) int cpu  = 5.5; int screen 

    java物件鎖對比分析

          說到鎖機制,不得不提到Thread執行緒,而又不得不提到synchronized關鍵字,這個單詞的意思是表示“同步”的意思。用它去修飾方法函式的時候,如果有多個執行緒同時呼叫這個方法函式的時候,那麼當一個執行緒獲得鎖的時候,其他的執行緒只