Java面試題之Java基礎部分 51-60題

51、啓動一個線程是用run()還是start()? 

啓動線程肯定要用start()方法

start()方法:用來啓動一個線程,這時此線程處於就緒狀態,然後通過調用此線程的run()方法來完成線程的運行操作。(當用start()開始一個線程後,線程就進入就緒狀態,使線程所代表的虛擬處理機處於可運行狀態,這意味着它可以由JVM調度並執行。這並不意味着線程就會立即運行。當cpu分配給它時間時,纔開始執行run()方法(如果有的話))。

run()方法:這只是一個方法,直接調用該方法只是把該方法的函數體給執行了一遍,並沒真正啓動一個線程

 

52、當一個線程進入一個對象的一個synchronized方法後,其它線程是否可進入此對象的其它方法?

分幾種情況:

1. 該對象其他方法前是否加了synchronized關鍵字,如果沒加,則能。

2. 如果其他個方法都加了synchronized關鍵字,並且內部有調用wait,則能

3. 如果其他個方法都加了synchronized關鍵字,並且內部沒有調用wait,則不能。

4. 如果其他方法是static,它用的同步鎖是當前類的字節碼,與非靜態的方法不能同步,因爲非靜態的方法用的是this

 

53、線程的基本概念、線程的基本狀態以及狀態之間的關係

進程中獨立運行的程序片段叫做線程。

Java中的線程有四種狀態分別是:運行、就緒、阻塞、死亡。


【擴展】進程與線程的區別:(面試題)

1.進程有獨立的進程空間,進程中的數據存放空間(堆空間和棧空間)是獨立的。

2.線程的堆空間是共享的,棧空間是獨立的,線程消耗的資源也比進程小,相互之間可以影響的。

 

54、簡述synchronizedjava.util.concurrent.locks.Lock的異同?

主要相同點:Lock能完成synchronized所實現的所有功能

主要不同點:Lock有比synchronized更精確的線程語義和更好的性能。synchronized會自動釋放鎖,而Lock一定要求程序員手工釋放,並且必須在finally從句中釋放。Lock還有更強大的功能,例如,它的tryLock方法可以非阻塞方式去拿鎖。

 

55、設計4個線程,其中兩個線程每次對j增加1,另外兩個線程對j每次減少

class ThreadTest {
    private int j;
    public static void main(String args[]) {
        ThreadTest tt = new ThreadTest();
        Inc inc = tt.new Inc();
        Dec dec = tt.new Dec();
        for (int i = 0; i < 2; i++) {
            Thread t = new Thread(inc);
            t.start();
            t = new Thread(dec);
            t.start();
        }
    }
 
    private synchronized void inc() {
        j++;
        System.out.println(Thread.currentThread().getName() + "-inc:" + j);
    }
 
    private synchronized void dec() {
        j--;
        System.out.println(Thread.currentThread().getName() + "-dec:" + j);
    }
 
    class Inc implements Runnable {
        public void run() {
            for (int i = 0; i < 100; i++) {
                inc();
            }
        }
    }
 
    class Dec implements Runnable {
        public void run() {
            for (int i = 0; i < 100; i++) {
                dec();
            }
        }
    }
}


56、子線程循環10次,接着主線程循環100,接着又回到子線程循環10次,接着再回到主線程又循環100,如此循環50次,請寫出程序。

public class TraditionalThreadCommunication {
	public static void main(String[] args) {
		final Business bussiness = new Business();
		new Thread(
		  new Runnable(){
			public void run() {
				for(int j=1; j<=50;j++){
					bussiness.sub(j);
				}
			}  
		  }		
		).start();
		
		new Thread(
			new Runnable(){
				public void run() {
					for(int j=1; j<=50;j++){
						bussiness.main(j);
					}	
				}  
			  }		
		).start();
	}
}

class Business{
	boolean bShouldSub = true;
	public synchronized void sub(int j){
		if(!bShouldSub){
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		for(int i=1;i<=10;i++){
			System.out.println("子線程循環。。。" + i);
		}
		bShouldSub = false;
		this.notify();
	}
	
	public synchronized void main(int j){
		if(bShouldSub){
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		for(int i=1;i<=30;i++){
			System.out.println("主線程循環。。。" + i);
		}
		bShouldSub = true;
		this.notify(); // 喚醒。
	}
}

下面使用jdk5中的併發庫來實現的: 

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ConditionThreadCommunication {
	public static void main(String[] args) {
		final Business business = new Business();
		/*子線程*/
		new Thread(new Runnable(){
			public void run() {
				for(int i = 1; i <= 50; i++){
					business.sub(i);
				}
			}
		}).start();
		
		/*主線程*/
		for(int i = 1; i <= 50; i++){
			business.main(i);
		}
	}
	
	static class Business {//處理線程安全歸爲一類,這樣用的就是同一把同步鎖
	private boolean subShouldRun = true; //當爲true時子線程執行,當爲false時主線程執行
	private Lock lock = new ReentrantLock();//創建一把鎖
	private Condition condition = lock.newCondition();//創建condition操作等待與喚醒操作
		
		public void sub(int i)
		{
			lock.lock();//打開鎖
			try
			{
				while(!subShouldRun)
				{
					try {
						//this.wait();//等待線程
						condition.await();//condition等待
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
				for(int j = 1; j <= 10; j++)
				{
					System.out.println("sub Thread sequence of " + j + ", loop of " + i);
				}
				subShouldRun = false;
				//this.notify();//喚醒線程
				condition.signal();//condition喚醒線程
			}finally
			{
				lock.unlock();//關閉鎖
			}
		}
		
		public void main(int i) 
		{
			lock.lock();//打開鎖
			try
			{
				while(subShouldRun)
				{
					try {
						//this.wait();
						condition.await();
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
				for(int j = 1; j <= 100; j++)
				{
					System.out.println("main Thread sequence of " + j + ", loop of " + i);
				}
				subShouldRun = true;
				//this.notify();
				condition.signal();
			}finally
			{
				lock.unlock();//關閉鎖
			}
		}
	}
}

57、介紹Collection框架的結構

Collection

    |-----List  有順序可重複

          |-----ArrayList 

                是數組實現  它是線程不安全的。它每一次添加後都會增長50%長度它在執行查找操作時效率比較高

          |-----LinkedList 是鏈表實現,它在執行修改或插入時效率比較高。 它是線程不安全的。

          |-----Vector 它也是數組實現,它是線程安全的 它每一次添加後都會增長100%長度無論是查找還是修改刪除操作效率都比較低。

    |-----Set  無順序不重複

          |----HashSet 底層實現是使用hash表,特點是無順序不可重複;HashSet維護元素的唯一性是使用元素的hashCodeequals實現的。

          |------LinkedHashSet  它的特點保證添加時的順序與取出時的順序一樣。

          |-----TreeSet 特點:有順序的不重複,底層實現是使用二叉樹

【擴展】類集框架的完整結構(Collection)

框架的完整結構(Collection)

1.類集框架最大的接口:CollectionMapIteratorEnumeration

2.Collection:存放單值

   |- List:允許有重複內容,有序

       |- ArrayList:異步處理,新的操作類,非線程安全。

       |- Vector:同步處理,舊的操作類,線程安全。支持Enumeration輸出

   |- Set:不允許有重複內容,無序,靠hashCoke()equals()進行重複的嚴重

       |- HashSet:無序存放

       |- TreeSet:有序存放,安Comparable排序

3.Map:存放一對值

   |- HashMap:新的類,異步處理,非線程安全,允許有null

   |- Hashtable:舊的類,同步處理,線程安全,不允許有null

        |- Properties:屬性操作類

   |- TreeMap:有序排列,按key排序,根據Comparable指定排序規則

4.Iterator:

   |- 迭代輸出,依靠Collection接口中的iterator方法輸出,是新的輸出標準

5.Enumeration:舊的輸出標準

 

58Collection框架中實現比較要實現什麼接口

comparable/comparator

【擴展】comparablecomparator的區別

1Comparable 用作默認的比較方式 ,需要覆蓋compareTo方法。

 Comparator 用作自定義的比較方式,當默認的比較方式不適用時或者沒有提供默認的比較方式,使用Comparator, 需要覆蓋compare方法

2comparable屬於java.lang包,comparator屬於java.util

3)像ArraysCollections中的排序方法,當不指定Comparator時使用的就是默認排序方式,也就是使用Comparable。指定Comparator時就是使用提供的比較器。 

sort(Object[]) 所有的對象都必須實現Comparable接口,它用來確定對象之間的大小關係 

sort(Object[], Comparator) 對象不必實現Comparable接口,由Comparator來確定對象之間的大小關係。

 

59、ArrayListVector的區別

(1)ArrayList :是數組實現  它是線程不安全的。它每一次添加後都會增長50%長度.它在執行查找操作時效率比較高;

2Vector 它也是數組實現,它是線程安全的 它每一次添加後都會增長100%長度,無論是查找還是修改刪除操作效率都比較低。(同步性和數據增長)


60、HashMapHashtable的區別

  HashMap:新的類,異步處理,非線程安全,允許有null

  Hashtable:舊的類,同步處理,線程安全,不允許有null


發佈了116 篇原創文章 · 獲贊 34 · 訪問量 17萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章