一次電話Java面試的問題總結(JDK8新特性、哈希衝突、HashMap原理、線程安全、Linux查詢命令、Hadoop節點)

面試涉及問題含有:javascript

Javahtml

  JDK8新特性java

  集合(哈希衝突、HashMap的原理、自動排序的集合TreeSet)node

  多線程安全問題linux

  String和StringBufferweb

JVM面試

  原理、運行流程、內部結構正則表達式

Linuxexpress

  查詢含有某字符串內容的命令grep編程

  查詢進程、GC狀態、殺死進程

Hadoop五種節點介紹

--------------------------------------------------------------------------------------------------------

 

JAVA:

一、JDK8新特性:

  • 函數接口Functional Interface

    只包含一個抽象方法的接口,也成爲SAM(Single Abstract Method單方法接口)類型的接口。

     例如Runnable接口的run()方法。JDK8新增了許多函數接口,其中一個重要的緣由就是支持Lambda表達式。

  • Lambda(拉姆達) 表達式(閉包) − Lambda容許把函數做爲一個方法的參數,函數做爲參數傳遞進方法中。

      一種匿名方法,能夠將函數接口中的函數做爲方法參數處理。在Java中Lambda表達式返回值是一個對象,這個對象必須是單方法接口

      lambda表達式的重要特徵:

        可選類型聲明:不須要聲明參數類型,編譯器能夠統一識別參數值。

        可選的參數圓括號:一個參數無需定義圓括號,但多個參數須要定義圓括號。

        可選的大括號:若是主體包含了一個語句,就不須要使用大括號。

        可選的返回關鍵字:若是主體只有一個表達式返回值則編譯器會自動返回值,大括號須要指定明表達式返回了一個數值。

      Lambda的設計能夠實現簡潔而緊湊的語言結構。最簡單的Lambda表達式可由逗號分隔的參數列表、->符號和語句塊組成,例如:

Arrays.asList( "a", "b", "d" ).forEach( e -> System.out.println( e ) );

Arrays.asList( "a", "b", "d" ).forEach( ( String e ) -> System.out.println( e ) );

Arrays.asList( "a", "b", "d" ).forEach( e -> {
    System.out.print( e );
    System.out.print( e );
} );


String separator = ",";
Arrays.asList( "a", "b", "d" ).forEach( 
    ( String e ) -> System.out.print( e + separator ) );

Arrays.asList( "a", "b", "d" ).sort( ( e1, e2 ) -> e1.compareTo( e2 ) );
等同於
Arrays.asList( "a", "b", "d" ).sort( ( e1, e2 ) -> {
    int result = e1.compareTo( e2 );
    return result;
} );
  • 方法引用 − 方法引用提供了很是有用的語法,能夠直接引用已有Java類或對象(實例)的方法或構造器。與lambda聯合使用,方法引用可使語言的構造更緊湊簡潔,減小冗餘代碼。

    Lambda表達式的一種特殊形式。當一個lambda表達式body中僅僅是調用某個方法,此時使用方法引用替代Lambda表達式。從形式上直接引用這個方法,比在lambda表達式body中引用在形式上更簡潔。

      方法引用經過方法的名字來指向一個方法。

      方法引用可使語言的構造更緊湊簡潔,減小冗餘代碼。

      方法引用使用一對冒號 :: 

Java 8使用兩個新概念擴展了接口的含義:默認方法和靜態方法。默認方法使得接口有點相似traits,不過要實現的目標不同。默認方法使得開發者能夠在 不破壞二進制兼容性的前提下,往現存接口中添加新的方法,即不強制那些實現了該接口的類也同時實現這個新加的方法。

默認方法和抽象方法之間的區別在於抽象方法須要實現,而默認方法不須要。接口提供的默認方法會被接口的實現類繼承或者覆寫,例子代碼以下:

private interface Defaulable {
    default String notRequired() { 
        return "Default implementation"; 
    }        
}
 
private static class DefaultableImpl implements Defaulable {
}
 
private static class OverridableImpl implements Defaulable {
    @Override
    public String notRequired() {
        return "Overridden implementation";
    }
}
Defaulable接口使用關鍵字default定義了一個默認方法notRequired()。DefaultableImpl類實現了這個接口,同時默認繼承了這個接口中的默認方法;OverridableImpl類也實現了這個接口,但覆寫了該接口的默認方法,並提供了一個不一樣的實現。

Java 8帶來的另外一個有趣的特性是在接口中能夠定義靜態方法,例子代碼以下:

private interface DefaulableFactory {
    // Interfaces now allow static methods
    static Defaulable create( Supplier< Defaulable > supplier ) {
        return supplier.get();
    }
}
下面的代碼片斷整合了默認方法和靜態方法的使用場景:
public static void main( String[] args ) {
    Defaulable defaulable = DefaulableFactory.create( DefaultableImpl::new );
    System.out.println( defaulable.notRequired() );
 
    defaulable = DefaulableFactory.create( OverridableImpl::new );
    System.out.println( defaulable.notRequired() );
}
輸出結果以下:
Default implementation
Overridden implementation

 

  • 默認方法 − 默認方法就是一個在接口裏面有了一個實現的方法。

    主要目的是爲了升級標準JDK接口,另外也是爲了能在JDK8中順暢的使用Lamb的表達式。

private interface DefaulableFactory {
    // Interfaces now allow static methods
    static Defaulable create( Supplier< Defaulable > supplier ) {
        return supplier.get();
    }
}
  • 新工具 − 新的編譯工具,如:Nashorn引擎 jjs、 類依賴分析器jdeps。

  • java批量數據操做bulk dataoperations

    目的是應用lambda函數來實現包含並行操做在內的多種數據處理功能,而支持並行數據操做是其關鍵內容。這個並行操做實在java7的java.util.concurrency的Fork/Join機制上實現的。

  • Stream API −新添加的Stream API(java.util.stream) 把真正的函數式編程風格引入到Java中。

  • Date Time API − 增強對日期與時間的處理。

  • Optional 類 − Optional 類已經成爲 Java 8 類庫的一部分,用來解決空指針異常。

  • Nashorn, JavaScript 引擎 − Java 8提供了一個新的Nashorn javascript引擎,它容許咱們在JVM上運行特定的javascript應用。

  • 重複註解:

    自從Java 5中引入註解以來,這個特性開始變得很是流行,並在各個框架和項目中被普遍使用。不過,註解有一個很大的限制是:在同一個地方不能屢次使用同一個註解。Java 8打破了這個限制,引入了重複註解的概念,容許在同一個地方屢次使用同一個註解。

    在Java 8中使用@Repeatable註解定義重複註解,實際上,這並非語言層面的改進,而是編譯器作的一個trick,底層的技術仍然相同。能夠利用下面的代碼說明:

  • package com.javacodegeeks.java8.repeatable.annotations;
     
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Repeatable;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
     
    public class RepeatingAnnotations {
        @Target( ElementType.TYPE )
        @Retention( RetentionPolicy.RUNTIME )
        public @interface Filters {
            Filter[] value();
        }
     
        @Target( ElementType.TYPE )
        @Retention( RetentionPolicy.RUNTIME )
        @Repeatable( Filters.class )
        public @interface Filter {
            String value();
        };
     
        @Filter( "filter1" )
        @Filter( "filter2" )
        public interface Filterable {        
        }
     
        public static void main(String[] args) {
            for( Filter filter: Filterable.class.getAnnotationsByType( Filter.class ) ) {
                System.out.println( filter.value() );
            }
        }
    }

    正如咱們所見,這裏的Filter類使用@Repeatable(Filters.class)註解修飾,而Filters是存放Filter註解的容器,編譯器儘可能對開發者屏蔽這些細節。這樣,Filterable接口能夠用兩個Filter註解註釋(這裏並無提到任何關於Filters的信息)。

    另外,反射API提供了一個新的方法:getAnnotationsByType(),能夠返回某個類型的重複註解,例如Filterable.class.getAnnoation(Filters.class)將返回兩個Filter實例,輸出到控制檯的內容以下所示: filter1 filter2

 

二、集合:

哈希衝突:

(見博客:https://www.cnblogs.com/wuchaodzxx/p/7396599.html)

若是兩個不一樣的元素,經過哈希函數得出的實際存儲地址相同怎麼辦?也就是說,當咱們對某個元素進行哈希運算,獲得一個存儲地址,而後要進行插入的時候,發現已經被其餘元素佔用了,其實這就是所謂的哈希衝突,也叫哈希碰撞。

哈希函數的設計相當重要,好的哈希函數會盡量地保證 計算簡單和散列地址分佈均勻,可是,咱們須要清楚的是,數組是一塊連續的固定長度的內存空間,再好的哈希函數也不能保證獲得的存儲地址絕對不發生衝突。那麼哈希衝突如何解決呢?哈希衝突的解決方案有多種:開放定址法(發生衝突,繼續尋找下一塊未被佔用的存儲地址),再散列函數法,鏈地址法,而HashMap便是採用了鏈地址法,也就是數組+鏈表的方式。

(1)開放定址法

這種方法也稱再散列法,其基本思想是:當關鍵字key的哈希地址p=H(key)出現衝突時,以p爲基礎,產生另外一個哈希地址p1,若是p1仍然衝突,再以p爲基礎,產生另外一個哈希地址p2,…,直到找出一個不衝突的哈希地址pi ,將相應元素存入其中。這種方法有一個通用的再散列函數形式:

Hi=(H(key)+di% m   i=1,2,…,n

其中H(key)爲哈希函數,m 爲表長,di稱爲增量序列。增量序列的取值方式不一樣,相應的再散列方式也不一樣。主要有如下三種:

線性探測再散列

dii=1,2,3,…,m-1

這種方法的特色是:衝突發生時,順序查看錶中下一單元,直到找出一個空單元或查遍全表。

二次探測再散列

di=12-1222-22…,k2-k2    ( k<=m/2 )

這種方法的特色是:衝突發生時,在表的左右進行跳躍式探測,比較靈活。

僞隨機探測再散列

di=僞隨機數序列。

(2)再哈希法

這種方法是同時構造多個不一樣的哈希函數:

Hi=RH1key)  i=1,2,…,k

當哈希地址Hi=RH1key)發生衝突時,再計算Hi=RH2key)……,直到衝突再也不產生。這種方法不易產生彙集,但增長了計算時間。

(3)鏈地址法

這種方法的基本思想是將全部哈希地址爲i的元素構成一個稱爲同義詞鏈的單鏈表,並將單鏈表的頭指針存在哈希表的第i個單元中,於是查找、插入和刪除主要在同義詞鏈中進行。鏈地址法適用於常常進行插入和刪除的狀況。

(4)創建公共溢出區

這種方法的基本思想是:將哈希表分爲基本表和溢出表兩部分,凡是和基本表發生衝突的元素,一概填入溢出表。

 

HashMap的底層原理:

見博客:https://www.cnblogs.com/chengxiao/p/6059914.html

HashMap的主幹是一個Entry數組。Entry是HashMap的基本組成單元,每個Entry包含一個key-value鍵值對。

//HashMap的主幹數組,能夠看到就是一個Entry數組,初始值爲空數組{},主幹數組的長度必定是2的次冪,至於爲何這麼作,後面會有詳細分析。
transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE;

Entry是HashMap中的一個靜態內部類。代碼以下:

複製代碼
    static class Entry<K,V> implements Map.Entry<K,V> {
        final K key;
        V value;
        Entry<K,V> next;//存儲指向下一個Entry的引用,單鏈表結構
        int hash;//對key的hashcode值進行hash運算後獲得的值,存儲在Entry,避免重複計算

        /**
         * Creates new entry.
         */
        Entry(int h, K k, V v, Entry<K,V> n) {
            value = v;
            next = n;
            key = k;
            hash = h;
        } 
複製代碼

簡單來講,HashMap由數組+鏈表組成的,數組是HashMap的主體,鏈表則是主要爲了解決哈希衝突而存在的,若是定位到的數組位置不含鏈表(當前entry的next指向null),那麼對於查找,添加等操做很快,僅需一次尋址便可;若是定位到的數組包含鏈表,對於添加操做,其時間複雜度爲O(n),首先遍歷鏈表,存在即覆蓋,不然新增;對於查找操做來說,仍需遍歷鏈表,而後經過key對象的equals方法逐一比對查找。因此,性能考慮,HashMap中的鏈表出現越少,性能纔會越好。

 

自動排序的集合:

TreeSet(樹集)是一個有序集合,能夠按照任何順序將元素插入該集合,當對該集合進行迭代時,各個值將自動以排序後的順序出現。TreeSet中的元素按照升序排列,缺省是按照天然順序進行排序,意味着TreeSet中的元素要實現Comparable接口,或者有一個自定義的比較器Comparator。

TreeSet底層使用的是TreeMap,TreeMap的底層實現是紅黑樹(詳細見http://www.cnblogs.com/xujian2014/p/4645943.html)。

 public TreeSet()
 {
        this(new TreeMap<E,Object>());
 }

使用示例:

複製代碼
public class Test
{
    public static void main(String[] args)
    {
        TreeSet<String> treeSet=new TreeSet<>();
        treeSet.add("Bili");
        treeSet.add("Amy");
        treeSet.add("cDy");
        for (String string : treeSet)
        {
            System.out.println(string);
        }
 }
複製代碼

  因爲String類實現了Comparable接口,它的compareTo方法是按照字典順序來對字符串進行排序,因此結果以下:

注意:

  一、TreeSet的排列順序必須是全局順序,也就是說任何兩個元素都是必須可比的,同時只有當他們比較相同時才返回0。

  二、若是樹集包含了n個元素,那麼平均須要進行log2n次比較,才能找到新元素的正確位置。

 

三、線程:

多線程安全運行:

在多個線程併發執行訪問同一個數據時,若是不採起相應的措施,將會是很是危險的。爲避免這種狀況發生,咱們要將多個線程對同一數據的訪問同步,確保線程安全。

所謂同步(synchronization)就是指一個線程訪問數據時,其它線程不得對同一個數據進行訪問,即同一時刻只能有一個線程訪問該數據,當這一線程訪問結束時其它線程才能對這它進行訪問。同步最多見的方式就是使用鎖(Lock),也稱爲線程鎖。鎖是一種非強制機制,每個線程在訪問數據或資源以前,首先試圖獲取(Acquire)鎖,並在訪問結束以後釋放(Release)鎖。在鎖被佔用時試圖獲取鎖,線程會進入等待狀態,直到鎖被釋放再次變爲可用。

 

Java裏面通常用如下幾種機制保證線程安全:

1.互斥同步鎖(悲觀鎖)

1)Synchorized

2)ReentrantLock

互斥同步鎖也叫作阻塞同步鎖,特徵是會對沒有獲取鎖的線程進行阻塞。

要理解互斥同步鎖,首選要明白什麼是互斥什麼是同步。簡單的說互斥就是非你即我,同步就是順序訪問。互斥同步鎖就是以互斥的手段達到順序訪問的目的。操做系統提供了不少互斥機制好比信號量,互斥量,臨界區資源等來控制在某一個時刻只能有一個或者一組線程訪問同一個資源。

Java裏面的互斥同步鎖就是Synchorized和ReentrantLock,前者是由語言級別實現的互斥同步鎖,理解和寫法簡單可是機制笨拙,在JDK6以後性能優化大幅提高,即便在競爭激烈的狀況下也能保持一個和ReentrantLock相差很少的性能,因此JDK6以後的程序選擇不該該再由於性能問題而放棄synchorized。ReentrantLock是API層面的互斥同步鎖,須要程序本身打開並在finally中關閉鎖,和synchorized相比更加的靈活,體如今三個方面:等待可中斷,公平鎖以及綁定多個條件。可是若是程序猿對ReentrantLock理解不夠深入,或者忘記釋放lock,那麼不只不會提高性能反而會帶來額外的問題。另外synchorized是JVM實現的,能夠經過監控工具來監控鎖的狀態,遇到異常JVM會自動釋放掉鎖。而ReentrantLock必須由程序主動的釋放鎖。

互斥同步鎖都是可重入鎖,好處是能夠保證不會死鎖。可是由於涉及到核心態和用戶態的切換,所以比較消耗性能。JVM開發團隊在JDK5-JDK6升級過程當中採用了不少鎖優化機制來優化同步無競爭狀況下鎖的性能。好比:自旋鎖和適應性自旋鎖,輕量級鎖,偏向鎖,鎖粗化和鎖消除。

2.非阻塞同步鎖

1) 原子類(CAS)

非阻塞同步鎖也叫樂觀鎖,相比悲觀鎖來講,它會先進行資源在工做內存中的更新,而後根據與主存中舊值的對比來肯定在此期間是否有其餘線程對共享資源進行了更新,若是舊值與指望值相同,就認爲沒有更新,能夠把新值寫回內存,不然就一直重試直到成功。它的實現方式依賴於處理器的機器指令:CAS(Compare And Swap)

JUC中提供了幾個Automic類以及每一個類上的原子操做就是樂觀鎖機制。

不激烈狀況下,性能比synchronized略遜,而激烈的時候,也能維持常態。激烈的時候,Atomic的性能會優於ReentrantLock一倍左右。可是其有一個缺點,就是隻能同步一個值,一段代碼中只能出現一個Atomic的變量,多於一個同步無效。由於他不能在多個Atomic之間同步。 

非阻塞鎖是不可重入的,不然會形成死鎖。

3.無同步方案

1)可重入代碼

在執行的任什麼時候刻均可以中斷-重入執行而不會產生衝突。特色就是不會依賴堆上的共享資源

2)ThreadLocal/Volaitile

線程本地的變量,每一個線程獲取一份共享變量的拷貝,單獨進行處理。

3)  線程本地存儲

若是一個共享資源必定要被多線程共享,能夠儘可能讓一個線程完成全部的處理操做,好比生產者消費者模式中,通常會讓一個消費者完成對隊列上資源的消費。典型的應用是基於請求-應答模式的web服務器的設計

 

四、String和StringBuffer

(1)String:是對象不是原始類型.爲不可變對象,一旦被建立,就不能修改它的值.對於已經存在的String對象的修改都是從新建立一個新的對象,而後把新的值保存進去.String 是final類,即不能被繼承

   String的值是不可變的,這就致使每次對String的操做都會生成新的String對象,不只效率低下,並且大量浪費有限的內存空間。 
   String a = "a"; //假設a指向地址0x0001 
   a = "b";//從新賦值後a指向地址0x0002,但0x0001地址中保存的"a"依舊存在,但已經再也不是a所指向的,a 已經指向了其它地址。 
   所以String的操做都是改變賦值地址而不是改變值操做。

(2)StringBuffer:是一個可變對象,當對他進行修改的時候不會像String那樣從新創建對象。它只能經過構造函數來創建對象被創建之後,在內存中就會分配內存空間,並初始保存一個null.向StringBuffer中賦值的時候能夠經過它的append方法.

StringBuffer是可變類,和線程安全的字符串操做類,任何對它指向的字符串的操做都不會產生新的對象。 每一個StringBuffer對象都有必定的緩衝區容量,當字符串大小沒有超過容量時,不會分配新的容量,當字符串大小超過容量時,會自動增長容量。 
   StringBuffer buf=new StringBuffer(); //分配長16字節的字符緩衝區 
   StringBuffer buf=new StringBuffer(512); //分配長512字節的字符緩衝區 
   StringBuffer buf=new StringBuffer("this is a test")//在緩衝區中存放了字符串,並在後面預留了16字節的空緩衝區。 

💗StringBuffer類中的方法要偏重於對字符串的變化例如追加、插入和刪除等,這個也是StringBuffer和String類的主要區別。
一、append方法
public StringBuffer append(boolean b)
該方法的做用是追加內容到當前StringBuffer對象的末尾,相似於字符串的鏈接。調用該方法之後,StringBuffer對象的內容也發生改變

二、deleteCharAt方法
public StringBuffer deleteCharAt(int index)
該方法的做用是刪除指定位置的字符,而後將剩餘的內容造成新的字符串。例如:
StringBuffer sb = new StringBuffer(「Test」);
sb. deleteCharAt(1);
該代碼的做用刪除字符串對象sb中索引值爲1的字符,也就是刪除第二個字符,剩餘的內容組成一個新的字符串。因此對象sb的值變爲」Tst」。
還存在一個功能相似的delete方法:
public StringBuffer delete(int start,int end)
該方法的做用是刪除指定區間之內的全部字符,包含start,不包含end索引值的區間。例如:
StringBuffer sb = new StringBuffer(「TestString」);
sb. delete (1,4);
該代碼的做用是刪除索引值1(包括)到索引值4(不包括)之間的全部字符,剩餘的字符造成新的字符串。則對象sb的值是」TString」。

三、insert方法
public StringBuffer insert(int offset, String s)
該方法的做用是在StringBuffer對象中插入內容,而後造成新的字符串。例如:
StringBuffer sb = new StringBuffer(「TestString」);
sb.insert(4,「false」);
該示例代碼的做用是在對象sb的索引值4的位置插入字符串false,造成新的字符串,則執行之後對象sb的值是」TestfalseString」。
四、reverse方法
public StringBuffer reverse()
該方法的做用是將StringBuffer對象中的內容反轉,而後造成新的字符串。例如:
StringBuffer sb = new StringBuffer(「abc」);
sb.reverse();
通過反轉之後,對象sb中的內容將變爲」cba」。

五、setCharAt方法
public void setCharAt(int index, char ch)
該方法的做用是修改對象中索引值爲index位置的字符爲新的字符ch。例如:
StringBuffer sb = new StringBuffer(「abc」);
sb.setCharAt(1,’D’);
則對象sb的值將變成」aDc」。

六、trimToSize方法
public void trimToSize()
該方法的做用是將StringBuffer對象的中存儲空間縮小到和字符串長度同樣的長度,減小空間的浪費。
七、構造方法:
StringBuffer s0=new StringBuffer();分配了長16字節的字符緩衝區
StringBuffer s1=new StringBuffer(512);分配了512字節的字符緩衝區
八、獲取字符串的長度: length()
StringBuffer s = new StringBuffer("www");
int i=s.length();
m.返回字符串的一部分值
substring(int start) //返回從start下標開始之後的字符串
substring(int start,int end) //返回從start到 end-1字符串
9.替換字符串
replace(int start,int end,String str)
s.replace(0,1,"qqq");
10.轉換爲不變字符串:toString()。

StringBuffer和StringBuilder類功能基本類似,主要區別在於StringBuffer類的方法是多線程、安全的,而 StringBuilder不是線程安全的,相比而言,StringBuilder類會略微快一點。對於常常要改變值的字符串應該使用 StringBuffer和StringBuilder類。 
線程安全 
StringBuffer 線程安全 
StringBuilder 線程不安全 
速度 
通常狀況下,速度從快到慢:StringBuilder>StringBuffer>String,這種比較是相對的,不是絕對的。 
總結 
(1)若是要操做少許的數據用 = String 
(2)單線程操做字符串緩衝區 下操做大量數據 = StringBuilder 
(3)多線程操做字符串緩衝區 下操做大量數據 = StringBuffer

 

JVM:

 一、運行流程

java程序通過一次編譯以後,將java代碼編譯爲字節碼也就是class文件,而後在不一樣的操做系統上依靠不一樣的java虛擬機進行解釋,最後再轉換爲不一樣平臺的機器碼,最終獲得執行。這樣咱們是否是能夠推演,若是要在mac系統上運行,是否是隻須要安裝mac java虛擬機就好了。那麼瞭解了這個基本原理後,咱們嘗試去作更深的研究,一個普通的java程序它的執行流程究竟是怎樣的呢?例如咱們寫了一段這樣的代碼:

public class HelloWorld { public static void main(String[] args) { System.out.print("Hello world"); } }

這段程序從編譯到運行,最終打印出「Hello world」中間通過了哪些步驟呢?咱們直接上圖:

二、內部結構

class文件被jvm裝載之後,通過jvm的內存空間調配,最終是由執行引擎完成class文件的執行。固然這個過程還有其餘角色模塊的協助,這些模塊協同配合才能讓一個java程序成功的運行

 

三、JVM內存空間包含:方法區、java堆、java棧、本地方法棧。

方法區是各個線程共享的區域,存放類信息、常量、靜態變量。

java堆也是線程共享的區域,咱們的類的實例就放在這個區域,能夠想象你的一個系統會產生不少實例,所以java堆的空間也是最大的。若是java堆空間不足了,程序會拋出OutOfMemoryError異常。

java棧是每一個線程私有的區域,它的生命週期與線程相同,一個線程對應一個java棧,每執行一個方法就會往棧中壓入一個元素,這個元素叫「棧幀」,而棧幀中包括了方法中的局部變量、用於存放中間狀態值的操做棧,這裏面有不少細節,咱們之後再講。若是java棧空間不足了,程序會拋出StackOverflowError異常,想想什麼狀況下會容易產生這個錯誤,對,遞歸,遞歸若是深度很深,就會執行大量的方法,方法越多java棧的佔用空間越大。

本地方法棧角色和java棧相似,只不過它是用來表示執行本地方法的,本地方法棧存放的方法調用本地方法接口,最終調用本地方法庫,實現與操做系統、硬件交互的目的。

PC寄存器,說到這裏咱們的類已經加載了,實例對象、方法、靜態變量都去了本身該去的地方,那麼問題來了,程序該怎麼執行,哪一個方法先執行,哪一個方法後執行,這些指令執行的順序就是PC寄存器在管,它的做用就是控制程序指令的執行順序。

執行引擎固然就是根據PC寄存器調配的指令順序,依次執行程序指令。

 

LINUX:

一、查找文件內容命令:

在使用linux時,常常須要進行文件查找。其中查找的命令主要有find和grep。兩個命令是有區的。

  區別:(1)find命令是根據文件的屬性進行查找,如文件名,文件大小,全部者,所屬組,是否爲空,訪問時間,修改時間等。 

               (2)grep是根據文件的內容進行查找,會對文件的每一行按照給定的模式(patter)進行匹配查找。

一.find命令

    基本格式:find  path expression

    1.按照文件名查找

    (1)find / -name httpd.conf  #在根目錄下查找文件httpd.conf,表示在整個硬盤查找
    (2)find /etc -name httpd.conf  #在/etc目錄下文件httpd.conf
    (3)find /etc -name '*srm*'  #使用通配符*(0或者任意多個)。表示在/etc目錄下查找文件名中含有字符串‘srm’的文件
    (4)find . -name 'srm*'   #表示當前目錄下查找文件名開頭是字符串‘srm’的文件

    2.按照文件特徵查找     

    (1)find / -amin -10   # 查找在系統中最後10分鐘訪問的文件(access time)
    (2)find / -atime -2   # 查找在系統中最後48小時訪問的文件
    (3)find / -empty   # 查找在系統中爲空的文件或者文件夾
    (4)find / -group cat   # 查找在系統中屬於 group爲cat的文件
    (5)find / -mmin -5   # 查找在系統中最後5分鐘裏修改過的文件(modify time)
    (6)find / -mtime -1   #查找在系統中最後24小時裏修改過的文件
    (7)find / -user fred   #查找在系統中屬於fred這個用戶的文件
    (8)find / -size +10000c  #查找出大於10000000字節的文件(c:字節,w:雙字,k:KB,M:MB,G:GB)
    (9)find / -size -1000k   #查找出小於1000KB的文件

    3.使用混合查找方式查找文件

    參數有: !,-and(-a),-or(-o)。

    (1)find /tmp -size +10000c -and -mtime +2   #在/tmp目錄下查找大於10000字節並在最後2分鐘內修改的文件
         (2)find / -user fred -or -user george   #在/目錄下查找用戶是fred或者george的文件文件
         (3)find /tmp ! -user panda  #在/tmp目錄中查找全部不屬於panda用戶的文件

2、grep命令

     基本格式:find  expression

命令:grep 
    格式:grep [option] pattern filenames 
    功能:逐行搜索所指定的文件或標準輸入,並顯示匹配模式的每一行。 
    選項:-i    匹配時忽略大小寫 
  -v 找出模式失配的行 
    例如:% grep -i 'java*' ./test/run.sh 

     1.主要參數

    [options]主要參數:
    -c:只輸出匹配行的計數。
    -i:不區分大小寫
    -h:查詢多文件時不顯示文件名。
    -l:查詢多文件時只輸出包含匹配字符的文件名。
    -n:顯示匹配行及行號。
    -s:不顯示不存在或無匹配文本的錯誤信息。
    -v:顯示不包含匹配文本的全部行。

    pattern正則表達式主要參數:
    \: 忽略正則表達式中特殊字符的原有含義。
    ^:匹配正則表達式的開始行。
    $: 匹配正則表達式的結束行。
    \<:從匹配正則表達 式的行開始。
    \>:到匹配正則表達式的行結束。
    [ ]:單個字符,如[A]即A符合要求 。
    [ - ]:範圍,如[A-Z],即A、B、C一直到Z都符合要求 。
    .:全部的單個字符。
    * :有字符,長度能夠爲0。

    2.實例  

  (1)grep 'test' d*  #顯示全部以d開頭的文件中包含 test的行
  (2)grep ‘test’ aa bb cc    #顯示在aa,bb,cc文件中包含test的行
  (3)grep ‘[a-z]\{5\}’ aa   #顯示全部包含每行字符串至少有5個連續小寫字符的字符串的行
  (4)grep magic /usr/src  #顯示/usr/src目錄下的文件(不含子目錄)包含magic的行
  (5)grep -r magic /usr/src  #顯示/usr/src目錄下的文件(包含子目錄)包含magic的行

  (6)grep -w pattern files :只匹配整個單詞,而不是字符串的一部分(如匹配’magic’,而不是’magical’),

 

二、GC狀態命令

一般運行命令以下:
jstat -gc 30996 3000
即:每3秒一次顯示進程號爲30996的java進程的GC狀況
或使用命令:jstat -gcutil 30996 3000
 
1.查進程
    ps命令查找與進程相關的PID號:
    ps a 顯示現行終端機下的全部程序,包括其餘用戶的程序。
    ps -A 顯示全部程序。
 
2.殺進程
   使用kill命令結束進程:kill xxx
   經常使用:kill -9 324
 
 

大數據:

HDFS節點、角色

1.Namenode名稱節點

   目錄的管理者,每個集羣都有一個,記錄實時的數據變化,若是沒有namenode,HDFS就沒法工做,系統中的文件將會所有丟失,就沒法將位於不一樣datanode上的文件快(blocks)重建文件。所以它的容錯機制頗有必要。

它主要負責:

  1. 接收用戶的請求;
  2. 維護文件系統的目錄結構;
  3. 管理文件與Block之間的練習;

2.Datanode數據節點

是文件系統的工做節點,他們根據客戶端或者是namenode的調度存儲和檢索,而且按期向namenode發送他們所存儲的塊(block)的列表。

集羣中的每一個服務器都運行一個DataNode後臺程序,這個後臺程序負責把HDFS數據塊讀寫到本地的文件系統。當須要經過客戶端讀/寫某個 數據時,先由NameNode告訴客戶端去哪一個DataNode進行具體的讀/寫操做,而後,客戶端直接與這個DataNode服務器上的後臺程序進行通 信,而且對相關的數據塊進行讀/寫操做。

它主要負責:

  1. 存放數據;
  2. 文件被分割以Block的形式被存儲在磁盤上;

3.Secondarynode

SecondaryNameNode是一個用來監控HDFS狀態的輔助後臺程序。就想NameNode同樣,每一個集羣都有一個SecondaryNameNode,而且部署在一個單獨的服務器上。

SecondaryNameNode不一樣於NameNode,它不接受或者記錄任何實時的數據變化,可是,它會與NameNode進行通訊,以便按期地保存HDFS元數據的快照。因爲NameNode是單點的,經過SecondaryNameNode的快照功能,能夠將NameNode的宕機時間和數據損失下降到最小。同時,若是NameNode發生問題,SecondaryNameNode能夠及時地做爲備用NameNode使用。

它主要將namenode image(fsimage)和Edit log合併的。

SecondaryNameNode的處理,是將fsimage和edites文件週期的合併,不會形成nameNode重啓時形成長時間不可訪問的狀況。

4.Resourcemanager

(1)與客戶端進行交互,處理來自於客戶端的請求,如查詢應用的運行狀況等。

(2)啓動和管理各個應用的ApplicationMaster,而且爲ApplicationMaster申請第一個Container用於啓動和在它運行失敗時將它從新啓動。

(3)管理NodeManager,接收來自NodeManager的資源和節點健康狀況彙報,並向NodeManager下達管理資源命令,例如kill掉某個container。

(4)資源管理和調度,接收來自ApplicationMaster的資源申請,而且爲其進行分配。這個是它的最重要的職能。

5.Nodemanager

NM是ResourceManager在每臺機器上的代理,負責容器管理,並監控它們的資源使用狀況,以及向ResourceManager/Scheduler提供資源使用報告。

總結: 

 (1)NameNode與ResourceManager分開部署(都是老大)

(2)NodeManager 也就是Resoucemanager 的「小弟」,它來作這事情,讀取hdfs 上的數據,數據保存在datanode上,因此若是數據集羣,datanode 與NodeManager ,必定要保存在同一個節點上

(3)Resoucemanager : 佔用端口:8088   進行調度資源(老大),進行任務分配的,誰來作這個事情

相關文章
相關標籤/搜索