Java基礎夯實 2

好久沒有更新過blog了。
回顧:

前面的一篇博客總結了:

  1. 九種基本數據類型的大小,以及他們的封裝類。
  2. Switch能否用string做參數?
  3. equals與==的區別。
  4. Object有哪些公用方法?
  5. Java的四種引用,強弱軟虛,用到的場景。
    五個問題,並進行了相關的詳細解釋,也請大家多多發表見解,相互學習。

6. Hashcode的作用

作用:用於查找的快捷性

注意事項:
1.兩個對象通過 == 或 equals方法比較結果爲true的時候,這兩個對象的hashCode也一定要相同。所以重寫equals方法的時候建議重寫hashCode方法,保證結果一致;
2.兩個對象的hashCode相同不代表兩個對象完全相同。也就是說hashCode並不能用來控制和判斷兩個對象是否相同。

舉例

Class A{
	public int age;
	public int stature;
	public String name;

	public A (int age, int stature, String name){
		this.age = age;
		this.stature = stature;
		this.name = name;
	}
	
	public A (){}
	
	public getAge(){
		return age;
	}

	public String getName(){
		return name;
	}

	public int getStature(){
		return stature;
	}
	
	@Override
	public boolean equals(Object obj){
		if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        A a = (A) obj;
        if (a.getAge() != this.getAge())
	        return false;
	    if (a.getName() != null && !a.getName().equals(this.getName()))
		    return false;
		if (a.getStature() != this.getStature())
			return false;
        return true;
	}

	@Override
	public int hashCode(){
		return name.leng() + stature + age;
	}
}

1.equals方法和 == 比較結果爲true, hashCode也要相同

A a = new A(1, 175, “uana”);
A b = a;
b.equals(a); // b == a;

2.equals方法比較結果爲true,hashCode結果也要一致

A a = new A(1, 175, “uana”);
A b = new A(1, 175, “uana”);
b.equals(a); // true

3.hashCode相同不代表是同一個對象

A a = new A(1, 175, “uana”);
A b = new A(5, 170, “uana”);
b.equals(a); // false
b.hashCode() == a.hashCode(); // true

下面說一下使用hashCode怎麼樣提高查找速度(代碼中有些邏輯判斷不合理,大體思路已經表現出來)
public class MyHashMap {
	/*根據hashCode存放數據,查詢數據的時候會減少查詢次數*/
    private static Map<Integer, List<A>> map = new HashMap();

    public static void put(A a) {
        if (map.containsKey(a.hashCode())) {
            if (!map.get(a.hashCode()).contains(a)) {
                map.get(a.hashCode()).add(a);
            }
        } else {
            List<A> list = new ArrayList<>();
            list.add(a);
            map.put(a.hashCode(), list);
        }
    }

    public static A get(int hashCode, A target) {
        if (map == null || map.size() == 0) {
            return "";
        }

        if (map.get(hashCode).contains(target)) {
            for (int i = 0; i < map.get(hashCode).size(); i++) {
                if (target == map.get(hashCode).get(i)) {
	                // 有效減少查詢次數
                    return map.get(hashCode).get(i);
                }
            }
        }
        return "";
    }
}

注:上面舉得例子是一個類(A)的情況下。同理還有可能出現不同類的對象的hashCode值是相同的情況。

總結:hashCode不同代表肯定不是同一個對象。它的作用是用來分離存儲對象的,通過hashCode值來存儲數據,在查找的時候能有效提高查詢速度。


7. 進程和線程

Part one 兩者的區別

對於應用層開發者而言,進程就是一個正在執行的(運行的)應用程序。線程就是進程內部的一個執行序列,一個進程可以有多個線程。線程依附於進程而存在。也可以把線程看做是一個輕量級的進程(實際上不是進程)。


Part two 創建線程的方式

1.繼承Thread類
2.實現Runnable接口
3.應用程序可以使用Executor框架來創建線程池

實現Runnable接口這種方式更受歡迎,因爲不需要繼承Thread類。因爲Java不支持多繼承,所以很多情況下在應用設計中會優先考慮使用Runnable接口。另外使用線程池也是一個很不錯的選擇。


Part three

線程的狀態
1.就緒狀態(Runnable): 線程準備運行,但是不代表立刻就能開始執行。
2.運行中(Running):進程正在執行線程中的代碼邏輯。
3.等待中(Waiting):線程處於阻塞狀態,等待外部的代碼邏輯處理結束。
4.睡眠中(Sleeping):線程被強制睡眠。
5.I/O阻塞(Blocked on I/O):等待I/O操作完成。
6.同步阻塞狀態(Blocked on Synchronization):此刻線程在等待獲取到鎖。
7.死亡(Dead):線程執行結束。

注意事項:不建議手動調用stop來結束線程(這樣操作不安全,所以不建議這樣操作。可以考慮在線程執行中加入邏輯控制來結束線程)。


8.如何做線程同步

關鍵詞:synchronized

實際應用中的作用點:
1.修飾實例方法,作用與當前實例加鎖。進入同步代碼前要獲取當前實例的鎖
2.修飾靜態方法,作用於當前類對象加鎖,進入同步代碼前要獲得當前類對象的鎖
3.修飾代碼塊。指定加鎖對象,對給定的對象加鎖,進入同步代碼塊之前要獲得給定對象的鎖

下面出相應的例子:代碼中會標註注意點

public class NormalMothedSync implements Runnable{
	// 共享資源
	static int num = 0;

	/**
	 * synchronized 修飾實例方法
	 */
	public synchronized void increase(){
		num++;
	}

	@Override
	public void run(){
		for(int i=0; i<1000; i++){
			increase();
		}
	}

	public static void main(String[] args) throws InterruptedException{
		// 創建實體對象
		NormalMothedSync nms = new NormalMothedSync();
		// 注意:這裏兩個線程使用的runnable對象是同一個對象。感興趣的朋友可以試試,兩個線程的runnable不適用同一個對象試試結果
		Thread th_01 = new Thread(nms);
		Thread th_02 = new Thread(nms);
		th_01.start();
		th_02.start();
		// join含義:當前線程B等待A線程終止之後才能執行(前提是AB兩個線程使用的鎖是同一個鎖對象)
		th_01.join();
		th_02.join();
		
		// 輸出結果 2000
		System.out.println(num); 
	}
}

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