java面試題:


1.字節


byte一字節,8位
short兩字節 16位
int四字節32位
long八字節64位

2.string 與 stringbuffer


    創建對象:string字符串爲常量 ,stringBuffer 爲變量
 string 字符串改變是,舊的對象將會被垃圾回收機制處理
總結一下
  String:適用於少量的字符串操作的情況

  StringBuilder:適用於單線程下在字符緩衝區進行大量操作的情況

  StringBuffer:適用多線程下在字符緩衝區進行大量操作的情況

3.GC


GC(GarbageCollection)是垃圾回收機制,在Java中開發人員無法使用指針來自由的管理內存,GC是JVM對內存(實際上就是對象)進行管理的方式。GC使得Java開發人員擺脫了繁瑣的內存管理工作,讓程序的開發更有效率。
計數法,可達性
當兩個對象相互調用時,會被gc。

4.GC原理- 垃圾收集算法


分代收集算法 VS 分區收集算法

    分代收集(新生代-複製算法,老年代-標記清除算法,老年代-標記整理算法,永久代-方法區回收)
    當前主流VM垃圾收集都採用”分代收集”(Generational Collection)算法, 這種算法會根據對象存活週期的不同將內存劃分爲幾塊, 如JVM中的 新生代、老年代、永久代. 這樣就可以根據各年代特點分別採用最適當的GC算法:

        在新生代: 每次垃圾收集都能發現大批對象已死, 只有少量存活. 因此選用複製算法, 只需要付出少量存活對象的複製成本就可以完成收集.
        在老年代: 因爲對象存活率高、沒有額外空間對它進行分配擔保, 就必須採用“標記—清理”或“標記—整理”算法來進行回收, 不必進行內存複製, 且直接騰出空閒內存.
    分區收集
    上面介紹的分代收集算法是將對象的生命週期按長短劃分爲兩個部分, 而分區算法則將整個堆空間劃分爲連續的不同小區間, 每個小區間獨立使用, 獨立回收. 這樣做的好處是可以控制一次回收多少個小區間.
    在相同條件下, 堆空間越大, 一次GC耗時就越長, 從而產生的停頓也越長. 爲了更好地控制GC產生的停頓時間, 將一塊大的內存區域分割爲多個小塊, 根據目標停頓時間, 每次合理地回收若干個小區間(而不是整個堆), 從而減少一次GC所產生的停頓

5.反射作用


1.class:得到類的名字,類的包名、父類和實現的接口
2.構造器:構造器參數,參數類型
3.變量:變量名,類型
4.方法:方法名,方法的參數,方法的返回類型,以及調用方法
5.註解:類註解,方法註解,參數註解,變量註解。
6.泛型:獲取泛型
7.數組:獲取值,設置值

6.springmvc AND mybatis


springmvn:視圖,模型,控制器,view,modle,colltroller
mybatis:是一個基於Java的持久層框架。注重sql。配置dataSource,sqlSessionFactory,sqlSession

==數據結構

1.HashMap與HashTable

1.存儲:HashMap中key和value都允許爲null
2.線程安全:HashMap線程不安全的,而Hashtable線程安全的,因爲所以方法都是Synchronize的。
3.hash值不同: 
   哈希值的使用不同,HashTable直接使用對象的hashCode。而HashMap重新計算hash值。
   hashCode是jdk根據對象的地址或者字符串或者數字算出來的int類型的數值。
   Hashtable計算hash值,直接用key的hashCode(),而HashMap重新計算了key的hash值,Hashtable在求      hash值對應的位置索引時,用取模運算,而HashMap在求位置索引時,則用與運算,且這裏一般先用          hash&0x7FFFFFFF後,再對length取模,&0x7FFFFFFF的目的是爲了將負的hash值轉化爲正值,因爲hash值    有可 能爲負數,而&0x7FFFFFFF後,只有符號外改變,而後面的位都不變。
4.內部實現使用的數組初始化和擴容方式不同
   HashTable在不指定容量的情況下的默認容量爲11,而HashMap爲16,Hashtable不要求底層數組的容量        一定要爲2的整數次冪,而HashMap則要求一定爲2的整數次冪。
   Hashtable擴容時,將容量變爲原來的2倍加1,而HashMap擴容時,將容量變爲原來的2倍。
   Hashtable和HashMap它們兩個內部實現方式的數組的初始大小和擴容的方式。HashTable中hash數組默認大    ,增加的方式是 old*2+1。

==流

1.IO與NIO


1.面向流(Stream),面向塊(buffer)
2.非阻塞,阻塞
3.Java NIO的selectors允許一條線程去監控多個channels的輸入

==異常

1. error,Exception區別


ERROR:表示由JVM所偵測到的無法預期的錯誤,由於這是屬於JVM層次的嚴重錯誤,導致JVM無法繼續執行,因此,這是不可捕捉到的,無法採取任何恢復的操作,頂多只能顯示錯誤信息。
Exception:表示可恢復的例外,這是可捕捉到的.
Exceptin包括兩種:
1.  需要檢查的異常:必須拋出的,如io,sqlException ,可以處理
2.不需要檢查的異常:不拋出的,如nullPointException ,不可以處理,程序編寫錯誤。(RuntimeException)


#Thread
##狀態:![thread](C:\Users\Administrator\Desktop\JDK\thread.png)

初始化(準備):new就緒:start()等待: 主動等待:wait(), join() 主動睡眠:wait(senconds), join(senconds),sleep() 進入阻塞:synchronized()運行:run()死亡:run()結束;interrupt()

==線程

1.線程間怎麼通訊:


1.同步:synchronized
   private static void demo1(){
        String lock = "";
        new Thread(()->{
            util(lock);
        }).start();
        new Thread(()->{
            util(lock);
        }).start();
    }
    private static void util(String string){
        //如果傳入string一個對象,只能允許一個訪問,
        //           傳入不同對象,可以同時訪問。
        synchronized (string){
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("print ..." + string);
        }
    }
2.wait/notify機制
   private static void demo3() {
        Object lock = new Object();
        Thread A = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lock) {
                    System.out.println("A 1");
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("A 2");
                    System.out.println("A 3");
                }
    
            }
        });
        Thread B = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lock) {
                    System.out.println("B 1");
                    System.out.println("B 2");
                    System.out.println("B 3");
    
                    lock.notify();
                }
            }
        });
        A.start();
        B.start();
    }
3.join() 等待另一個線程完成
   private static void demo2() {
        Thread A = new Thread(new Runnable() {
            @Override
            public void run() {
                printNumber("A");
            }
        });
    
        Thread B = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("B 開始等待 A");
                try {
                    A.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    
                printNumber("B");
            }
        });
    
        B.start();
        A.start();
    }
   private static void printNumber(String threadName) {
        int i=0;
        while (i++ < 3) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(threadName + " print: " + i);
        }
    }
4.CountdownLatch(計數器),CyclicBarrier(同時進行)
  private static void runDAfterABC() {
        int worker = 3;
        CountDownLatch countDownLatch = new CountDownLatch(worker);
        new Thread(() -> {
            System.out.println("D is waiting for other three threads");
            try {
                countDownLatch.await();
                System.out.println("All done, D starts working");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
        }).start();
        for (char threadName='A'; threadName <= 'C'; threadName++) {
            final String tN = String.valueOf(threadName);
            new Thread(() -> {
                System.out.println(tN + " is working");
                try {
                    Thread.sleep(100);
                } catch (Exception e) {
                    e.printStackTrace();
                }
    
                System.out.println(tN + " finished");
                countDownLatch.countDown();
            }).start();
        }
    }
    
    /**
     * 每個線程逐漸進入等待
     * 都進入等待狀態時:同時觸發
     */
    private static void runABCWhenAllReady() {
        int runner = 3;
        CyclicBarrier cyclicBarrier = new CyclicBarrier(runner);
        final Random random = new Random();
        for (char runnerName='A'; runnerName <= 'C'; runnerName++) {
            final String rN = String.valueOf(runnerName);
            new Thread(() -> {
                long prepareTime = random.nextInt(10000) + 100;
                System.out.println(rN + " is preparing for time: " + prepareTime);
                try {
                    Thread.sleep(prepareTime);
                    System.out.println(rN + " is prepared, waiting for others");
                    cyclicBarrier.await(); // 當前運動員準備完畢,等待別人準備好
                } catch (Exception e) {
                    e.printStackTrace();
                }
                System.out.println(rN + " starts running"); // 所有運動員都準備好了,一起開始跑
            }).start();
        }
    }
5.FutureTask

   private static void doTaskWithResultInWorker() {
        Callable<Integer> callable = () -> {
            System.out.println("Task starts");
            Thread.sleep(1000);
            int result = 0;
            for (int i=0; i<=100; i++) {
                result += i;
            }
            System.out.println("Task finished and return result");
            return result;
        };
    
        FutureTask<Integer> futureTask = new FutureTask<>(callable);
        new Thread(futureTask).start();
        try {
            System.out.println("Before futureTask.get()");
            System.out.println("Result: " + futureTask.get());
            System.out.println("After futureTask.get()");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

2.守護線程

private static void doemon(){


    // 守護線程,當程序中只剩下守護線程時程序終止。
    Thread t = new Thread(() -> {
        for (int i = 0; i < 10; i++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("i=" + i);
        }
    });
    //t.setDaemon(true);//this is set t thread as a daemon thread.
    t.start();
    try {
        Thread.sleep(2000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println("main thread exit.");
}

3.線程安全與線程不安全


線程安全:一個線程訪問一個數據對象時,將對象鎖住,其他線程不能訪問,直到此線程操作結束,纔將該對象釋放。
線程不安全:多個線程可以同時訪問一個對象,容易造成數據污染,髒讀。

==MYSQL

1.事務的隔離級別


                  √: 可能出現    ×: 不會出現
                    髒讀 不可重複讀 幻讀
Read uncommitted        
Read committed      ×     
Repeatable read     ×   ×   
Serializable        ×   ×   ×

Read uncommitted 讀未提交

公司發工資了,領導把5000元打到singo的賬號上,但是該事務並未提交,而singo正好去查看賬戶,發現工資已經到賬,是5000元整,非常高興。可是不幸的是,領導發現發給singo的工資金額不對,是2000元,於是迅速回滾了事務,修改金額後,將事務提交,最後singo實際的工資只有2000元,singo空歡喜一場。
出現上述情況,即我們所說的髒讀,兩個併發的事務,“事務A:領導給singo發工資”、“事務B:singo查詢工資賬戶”,事務B讀取了事務A尚未提交的數據。
當隔離級別設置爲Read uncommitted時,就可能出現髒讀,如何避免髒讀,請看下一個隔離級別。

Read committed 讀提交

singo拿着工資卡去消費,系統讀取到卡里確實有2000元,而此時她的老婆也正好在網上轉賬,把singo工資卡的2000元轉到另一賬戶,並在singo之前提交了事務,當singo扣款時,系統檢查到singo的工資卡已經沒有錢,扣款失敗,singo十分納悶,明明卡里有錢,爲何......
出現上述情況,即我們所說的不可重複讀,兩個併發的事務,“事務A:singo消費”、“事務B:singo的老婆網上轉賬”,事務A事先讀取了數據,事務B緊接了更新了數據,並提交了事務,而事務A再次讀取該數據時,數據已經發生了改變。
當隔離級別設置爲Read committed時,避免了髒讀,但是可能會造成不可重複讀。
大多數數據庫的默認級別就是Read committed,比如Sql Server , Oracle。如何解決不可重複讀這一問題,請看下一個隔離級別。

Repeatable read 重複讀

當隔離級別設置爲Repeatable read時,可以避免不可重複讀。當singo拿着工資卡去消費時,一旦系統開始讀取工資卡信息(即事務開始),singo的老婆就不可能對該記錄進行修改,也就是singo的老婆不能在此時轉賬。
雖然Repeatable read避免了不可重複讀,但還有可能出現幻讀。
singo的老婆工作在銀行部門,她時常通過銀行內部系統查看singo的信用卡消費記錄。有一天,她正在查詢到singo當月信用卡的總消費金額(select sum(amount) from transaction where month = 本月)爲80元,而singo此時正好在外面胡吃海塞後在收銀臺買單,消費1000元,即新增了一條1000元的消費記錄(insert transaction ... ),並提交了事務,隨後singo的老婆將singo當月信用卡消費的明細打印到A4紙上,卻發現消費總額爲1080元,singo的老婆很詫異,以爲出現了幻覺,幻讀就這樣產生了。
注:Mysql的默認隔離級別就是Repeatable read。

Serializable 序列化

Serializable是最高的事務隔離級別,同時代價也花費最高,性能很低,一般很少使用,在該級別下,事務順序執行,不僅可以避免髒讀、不可重複讀,還避免了幻像讀。 

2.mysql索引有哪幾種:

MySQL裏的索引類型主要有以下幾種。

1. B-Tree索引

最常見的索引類型,基於B-Tree數據結構。B-Tree的基本思想是,所有值(被索引的列)都是排過序的,每個葉節點到跟節點距離相等。所以B-Tree適合用來查找某一範圍內的數據,而且可以直接支持數據排序(ORDER BY)。但是當索引多列時,列的順序特別重要,需要格外注意。InnoDB和MyISAM都支持B-Tree索引。InnoDB用的是一個變種B+Tree,而MyISAM爲了節省空間對索引進行了壓縮,從而犧牲了性能。

2. Hash索引

基於hash表。所以這種索引只支持精確查找,不支持範圍查找,不支持排序。這意味着範圍查找或ORDER BY都要依賴server層的額外工作。目前只有Memory引擎支持顯式的hash索引(但是它的hash是nonunique的,衝突太多時也會影響查找性能)。Memory引擎默認的索引類型即是Hash索引,雖然它也支持B-Tree索引。

例子:

CREATE TABLE testhash (
    fname VARCHAR(50) NOT NULL,
    lname VARCHAR(50) NOT NULL,
    KEY USING HASH(fname)
) ENGINE =MEMORY;

3. Spatial (R-Tree)(空間)索引

只有MyISAM引擎支持,並且支持的不好。可以忽略。

4. Full-text索引

主要用來查找文本中的關鍵字,而不是直接與索引中的值相比較。Full-text索引跟其它索引大不相同,它更像是一個搜索引擎,而不是簡單的WHERE語句的參數匹配。你可以對某列分別進行full-text索引和B-Tree索引,兩者互不衝突。Full-text索引配合MATCH AGAINST操作使用,而不是一般的WHERE語句加LIKE。

問題處理:

1.分佈式事務

分佈式事務,本質上是對多個數據庫的事務進行統一控制,
按照控制力度可以分爲:不控制、部分控制和完全控制。
不控制就是不引入分佈式事務,部分控制就是各種變種的兩階段提交,包括上面提到的消息事務+最終一致性、TCC模式,而完全控制就是完全實現兩階段提交。部分控制的好處是併發量和性能很好,缺點是數據一致性減弱了,完全控制則是犧牲了性能,保障了一致性,具體用哪種方式,最終還是取決於業務場景。作爲技術人員,一定不能忘了技術是爲業務服務的,不要爲了技術而技術,針對不同業務進行技術選型也是一種很重要的能力http://blog.csdn.net/mine_song/article/details/64118963


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章