Java面試題和解答(三)

一、這段代碼大多數狀況下運行正常,可是某些狀況下會出問題。何時會出現什麼問題?如何修正?css

public class MyStack {  
    private List<String> list = new ArrayList<String>();  
  
    public synchronized void push(String value) {  
        synchronized (this) {  
            list.add(value);  
            notify();  
        }  
    }  
  
    public synchronized String pop() throws InterruptedException {  
        synchronized (this) {  
            if (list.size() <= 0) {  
                wait();  
            }  
            return list.remove(list.size() - 1);  
        }  
    }  
}

list.remove(list.size() - 1);這句代碼有可能引起數組下標越界html

緣由(答案來源互聯網,非本人回答):
假設其中一種情形呵!出問題的情形可能不少,但原理都差很少。下面的標號表明程序時序的前後順序。
1,初始化時list的值爲0,而後線程1調用了pop,因而被wait了,而後釋放了鎖。
2,線程2調用push,在notify以前有線程3調用pop(記住這時候線程1尚未被喚醒,還在wait住),此時線程3會由於等待鎖而掛起,或自旋,反正就是在等待鎖可用。
3,而後線程2繼續往下執行,notify被執行(但這時候線程1是不會喚醒的,由於鎖還在線程2佔用),線程2退出push方法,釋放內置鎖,此時,線程1和線程3都在內置鎖等待隊列裏面。因爲synchronized是無法保證線程競爭的公平性,因此線程1和線程3均可能獲得鎖。
4,假設線程1競爭到了鎖,不會出問題,正常去除list值,而後remove,執行完後線程3執行,一樣被wait住。
5,假設線程3競爭到了鎖,問題來了,線程3會判斷到list的size不爲0,因而remove,因此list的size就爲0了,而後線程 3釋放鎖,這時候,線程1就獲得鎖,因而從wait中醒來,繼續執行,而後直接調用list的remove,因爲list的size=0,那麼remove(-1),越界錯誤就產生了。java

改進:git

改進1,——最小代碼改動,就在remove以前再檢查list.size==0
改進2,——去掉push和pop方法內的第二重鎖檢查,我確實沒有發現這個鎖會有什麼用,反而耗性能。 固然這裏仍是要有方案1的判斷(謝謝一樓提醒)。
改進3,——從新設計,若是是我來設計這麼一個生產者,消費者模式。我更願意用LinkedBlockingQueue,它有take方法阻塞消費者直到隊列可用。並且還有offer方法阻塞生產者直到隊列能夠插入,能夠有效的阻止OOM。數據庫

二、寫一段代碼實現銀行轉賬功能,從轉出賬號中扣除轉賬金額,給轉入賬號增長轉賬金額,保證兩個操做 要麼同時成功,要麼同時失敗數組

public interface ITransfer {
    /**
   * fromAccountId  轉出賬號 toAccountId 轉入賬號 amount 轉賬金額
     **/

    public void transferInner(String fromAccountId, String toAccountId, BigDecimal amount);

    /**
     * 外部轉賬-轉出,從轉出賬號中扣除轉賬金額 fromAccountId 轉出賬號 amount 轉賬金額
     **/
    public void transferOut(String fromAccountId, BigDecimal amount);

    /**
     * 外部轉賬-轉入,給轉入賬號增長轉賬金額 toAccountId 轉入賬號 amount 轉賬金額
     */

    public void transferIn(String toAccountId, BigDecimal amount);
}

這道題考察對事務的理解。若是轉出和轉入操做都在同一個應用裏面進行,使用數據庫的事務特性就能夠作到「要麼同時成功,要麼同時失敗」;不然就要用分佈式事務的方案來解決,先消化一下這篇文章《分佈式系統事務一致性解決方案》。分佈式

三、實現統計某一目錄下每一個文件中出現的字母個數、數字個數、空格個數及行數?性能

/*文本內容僅限數字,字母,及空格*/
import java.io.*;
class Ex6_5 {
    public static void main ( String[] args ) {
        String fileName = "C:/Hello.txt" , line;
        int i,j,f,k;
        try {
             BufferedReader in = new BufferedReader(new FileReader( fileName  ) );
             line = in.readLine();   //讀取一行內容
             while ( line != null ) { 
                    if(Character.isLetter(line))
                      i++;
                   else if(Character.isDigit(line))
                      j++;
                 else
                      f++;    
           line = in.readLine();
                      k++   
                 }
            in.close(); 
        System.out.println("字母"+i+"數字"+j+"空格"+j+"行數"+k)
        }
       catch ( IOException iox ) { 
            System.out.println("Problem reading " + fileName );  
        }
    }
}

四、假若有字符串「6sabcsfs33」 ,用最有快速的方法去掉字符「ab3」,不能用java內置字符串方法(indeOf,substring,replaceAll等)this

  String regx = "[^a|b|3]";
  String temp = "6sabcsssfsfs33";
  Pattern p = Pattern.compile(regx);
  Matcher m = p.matcher(temp);
  while (m.find()) {
   System.out.print(m.group());
  }
相關文章
相關標籤/搜索