1. 程式人生 > >java多執行緒面試題:三個執行緒順序列印ABC,重複10次

java多執行緒面試題:三個執行緒順序列印ABC,重複10次

這個面試題,比較經典。有不同的解決思路。有的博文是用Join去實現。我面試的時候也是第一個想到的是用join叫A執行緒等待B執行緒執行完再執行。這樣的思路能實現,但是不好。雖然當時湊合著說服了面試官。先把程式碼貼出來

private  Thread aThread,bThread,cThread;
	
	@Test
	public void test1() {
		
		aThread=new Thread(new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				System.out.println("A");
				try {
					bThread.start();
					bThread.join();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		});
		bThread=new Thread(new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				System.out.println("B");
				try {
					cThread.start();
					cThread.join();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		});
		cThread=new Thread(new Runnable() {
	
			@Override
			public void run() {
				// TODO Auto-generated method stub
				System.out.println("C");
				
				
			}
		});
		
		aThread.start();
		
		
	}
這個思路比較簡單。三個執行緒。啟動a,列印完A後;啟動b,列印完B後;啟動c。雖然能實現順序列印,但是會之後還會重複建立執行緒。這個面試題當時答的貌似有道理,同時跟面試官說了說多執行緒的知識,面試官還算滿意。回來後一考慮,太Low了。然後自己查資料研究了一下。下邊把正確答案貼出來
public class MyTest1 {

	private static Boolean flagA=true;
	private static Boolean flagB=false;
	private static Boolean flagC=false;
	
	public static void main(String[] args) {
		 final Object lock = new Object();
				
		Thread aThread=new Thread(new Runnable() {
			
			@Override
			public void run() {
				for(int i=0;i<10;) {
					
						synchronized (lock) {					
							
							if (flagA) {
								//執行緒A執行
								System.out.println("A");
								flagA=false;
								flagB=true;
								flagC=false;
								 lock.notifyAll();
								 i++;
								
							}else {								
								try {
									lock.wait();
								} catch (InterruptedException e) {
									// TODO Auto-generated catch block
									e.printStackTrace();
								}
							
							}
						}				
					
				}
				
				
			}
		});
		
		
		
		Thread bThread=new Thread(new Runnable() {
			
			@Override
			public void run() {
				for(int i=0;i<10;) {
					
					synchronized (lock) {
							if (flagB) {
								//執行緒執行
								System.out.println("B");
								 flagA=false;
								 flagB=false;
								 flagC=true;
								 lock.notifyAll();
								i++;
								
							}else {
								
								try {
									lock.wait();
								} catch (InterruptedException e) {
									// TODO Auto-generated catch block
									e.printStackTrace();
								}
							
							}
							
					}
						
						
					
				}
				
				
			}
		});
		

		Thread cThread=new Thread(new Runnable() {
			
			@Override
			public void run() {
				for(int i=0;i<10;) {
					
					synchronized (lock) {
						
							if (flagC) {
								//執行緒執行
								System.out.println("C");
								 flagA=true;
								 flagB=false;
								 flagC=false;
								 lock.notifyAll();
								i++;
								
							}else {
								
								try {
									lock.wait();
								} catch (InterruptedException e) {
									// TODO Auto-generated catch block
									e.printStackTrace();
								}
							
							}
							
							
						}
		
				}
				
			}
		});
		
		
		cThread.start();	
		bThread.start();
		aThread.start();
	}

親測通過。沒什麼問題。基本思路就是設定三個boolean變數和一個鎖。flag控制那個執行緒可以走,那個應該停下來。然後在列印後才i++。直到i<10的時候,執行緒停止。

下邊在送一個例項。寫一個多執行緒程式,交替輸出1,2,1,2,1,2......

public class OutputThread implements Runnable {

    private int num;
    private Object lock;
    
    public OutputThread(int num, Object lock) {
        super();
        this.num = num;
        this.lock = lock;
    }

    public void run() {
        try {
            while(true){
                synchronized(lock){
                    lock.notifyAll();
                    lock.wait();
                    System.out.println(num);
                }
            }
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }
    
    public static void main(String[] args){
        final Object lock = new Object();
        
        Thread thread1 = new Thread(new OutputThread(1,lock));
        Thread thread2 = new Thread(new OutputThread(2, lock));
        
        thread1.start();
        thread2.start();
    }

}
原理一樣,關鍵程式碼就是
 while(true){
                synchronized(lock){
                    lock.notifyAll();
                    lock.wait();
                    System.out.println(num);
                }
            }