java基礎---------多線程與反射


第一部分多線程:

java語言是爲數不多的支持多線程的語言。
進程:當程序進入內存運行時,即變成了一個進程。進程是處於運行過程中的程序,並且具有一定的獨立功能,進程是系統進行資源分配和調度的一個獨立單位。


硬盤和內存都可以存儲數據。硬盤是持久存儲設備,內存是臨時存儲設備,內存的數據,在斷電之後就消失了,內存的速度快。
進程特徵:
1、獨立性:每一個進程都擁有自己私有的地址空間。
2、動態性:程序只是一個靜態的指令集合,進程是一個正在系統中活動的指令集合。
3、併發性:多個進程可以在單個處理器上併發執行,多個進程之間不會互相影響。


線程是進程的執行單元,執行路徑,使得同一個進程可以同時併發處理多個任務。


一個進程中至少有一個線程在負責該進程的運行。
對於一個CPU而言,它在某個時間點只能執行一條線程。CPU在不斷地在進行這些線程之間輪換執行。這種切換速度是快速的,我們感受不到這種速度。


在多線程中,由於存在着CPU切換線程來執行的過程,因此就讓多線程運行有了一個隨機性。


JVM的多線程中,至少有兩個,一個是負責自定義代碼運行的。
一個是負責垃圾回收的。
案例:
class RubbishDemo{
	public void finalize(){
		System.out.println("垃圾回收器執行");
	}
}


class Demo{
	public static void main(String [] args){
		new RubbishDemo();
		new RubbishDemo();
		new RubbishDemo();
		System.gc();
	 
	}
}


注意:通過控制檯輸出,我們會發現,輸出"垃圾回收期執行"這句話的次數不同,有的是一次,有的是兩次,有的是三次等,這就說明,雖然我們調用了垃圾回收器,但是CPU在處理指令的時候,並不是立即就執行。  


線程的任務都封裝在特定的區域中,比如主線程運行的任務在main方法中,main()的方法體就是主線程的線程執行體;而垃圾回收線程在收垃圾時,都會運行finalize().


編程使用多線程的優點:
1、進程之間不能共享內存,但線程之間共享內存非常容易。
2、系統創建進程時,需要爲該進程重新分配系統資源,但創建線程代價小得多,因此使用多線程來實現多任務併發比多進程的效率高。
3、Java語言內置了多線程功能支持,而不是單純地作爲底層操作系統的調度方法,從而簡化了java的多線程編程。


第二部分Thread類
1、Java使用Thread類代表線程,所有線程對象都是必須是Thread類或其子類的實例。

//由於Thread類是java.lang包下的類,因此我們在這裏沒有導包。
public class ThreadDemo extends Thread {
	private int i;
	public void run(){
		for(;i<5;i++){
				//getName()該方法是Thread類的實例方法,該方法返回調用該方法的線程名字。
			System.out.println(Thread.currentThread().getName()+""+i);
			System.out.println(this.getName()+"\t"+i);
			System.out.println(getName()+"\t"+"\t"+i);
		}
	}
	public static void main(String [] args){		
			//currentThread()爲Thread類的靜態方法,該方法總是返回當前正在執行的線程對象。
			System.out.println(Thread.currentThread().getName());		
				new ThreadDemo().start();
				new ThreadDemo().start();		
		//在默認情況下,主線程的名字爲main,用戶啓動的多個線程的名字一次爲Thread-0、Thread-1、Thread-2...等。
		
	}
}


輸出結果:
main
Thread-00
Thread-0 0
Thread-0 0
Thread-01
Thread-0 1
Thread-10
Thread-0 1
Thread-1 0
Thread-02
Thread-1 0
Thread-0 2
Thread-11
Thread-0 2
Thread-1 1
Thread-03
Thread-1 1
Thread-0 3
Thread-12
Thread-0 3
Thread-04
Thread-0 4
Thread-0 4
Thread-1 2
Thread-1 2
Thread-13
Thread-1 3
Thread-1 3
Thread-14
Thread-1 4
Thread-1 4


該程序繼承了Thread類,並且實現了他的run()方法,該run()方法裏的代碼執行流就是該線程所需要完成的任務。這裏一共有三個線程。一個是主線程,兩個是子線程。
this.getName()調用的是堆裏面的thread-0;
Thread.currentThread.getName()指向的是棧內存中Thread-0多線程區域的。;
因此如果直接在主方法中,用對象名調用run()的話,Thread.currentThread.getName()就會輸出的是主線程的名字:main了。


start()和run()的區別:
調用start()方法,可以啓動線程,讓線程去執行run()中的任務。
調用run()方法,則仍是主線程在運行,線程並未開啓,執行run()的是主線程,而不是子線程。 




2、Runnable接口
Thread類實現了Runnable接口。我們在定義Runnable接口的實現類時,需要重寫該接口的run()方法,該方法的方法體同樣是該線程的線程執行體。Runnable接口實現了任務與線程分離的思想。也就是採用Runnable接口的方式創建的多個線程可以共享線程的實例屬性。
創建線程的第二種方式:
1、定義一個類實現新Runnable。
2、覆蓋Runnable接口中的run方法,將線程要運行的任務代碼存儲到該方法中。
3、通過Thread類創建線程對象,並將實現了Runnable接口的對象作爲Thread類的構造函數的參數進行傳遞。
4、調用Thread類的start方法,開啓線程。


class SaleTickets implements Runnable{
	private int tickets=100;
	public void run(){
		while(true){
			if(tickets>0){
				System.out.println(Thread.currentThread.getName()+"*****"+tickets--);
			}
		}	
	}
}


class TicketDemo{
	public static void main(String   []args){
		SaleTickets st=new SaleTickets();
		Thread t1=new Thread(st);
		Thread t2=new Thread(st);
		Thread t3=new Thread(st);
		Thread t4=new Thread(st);
		t1.start();
		t2.start();
		t3.start();
		t4.start();		
	}
}



線程安全不安全?

當一個線程在操作數據時,其他的線程參與了運算,造成了數據的錯誤,這就是線程不安全。只要保證多條操作共享數據的代碼在某一時間段,被一條線程所執行,在執行期間不允許其他線程參與運算。


第三部分 反射

反射:就是把java類中的各種成分映射成相應的java類。
java程序中的許多對象在運行時都會出現兩種類型,編譯時類型和運行時類型。比如代碼People p=new Student();這裏產生了一個變量p,該變量在編譯時期類型爲People,在運行時期類型爲Student。


Class和class的區別:
在java程序中,java中的類用於描述一類事物的共性,也就是class,比如class People{};這個People類中有名字,年齡等屬性,有吃飯睡覺等方法,還有構造函數。
Class指的是java程序中的各個java類是屬於同一類事物,都是java程序的類,這些類成爲Class。比如動物對於的是Animal類,java類對應的就是Class。也就是Class是java程序各個java類的總稱,它是反射的基石,通過Class類來使用反射。


獲取Class對象的三種方式:
1、使用Class類的forName(String clazzName)靜態方法。該方法需要傳入字符串參數,該字符串參數的值是某個類的全限定類名(必須添加完整包名);
2、調用某個類的class屬性來獲取該類對應的Class對象。例如Person.class將會返回Person類對應的Class對象。
3、調用某個對象的getClass()方法。該方法時java.lang.Object類中的一個方法,所以所有的java對象都可以調用該方法,該方法將會返回該對象所屬類對應的Class對象。
第二種方法優點:代碼更安全,程序性能更好。


一、從Class中獲取信息:
1、獲取Class對應類所包含的構造器:
Constructor<T> getConstructor(Class<?>...parameterTypes):返回此Class對象對應類的指定public構造器。
Constructor<?> [] getConstructors():返回此Class對象對應類的所有public構造器。
Constructor<T>getDeclaredConstructor(Class<?>...parameterTypes):返回此Class對象對應類的指定構造器。
Constructor<?>[] getDeclaredConstructors():返回此Class對象對應類的所有構造器。


2、獲取Class對應類所包含的方法
Method getMethod(String name,Class<?>...parameterTypes):返回此Class對象對應類的指定public方法
Method [] getMethod():返回此Class對象所表示的類的所有public方法。
Method getDeclaredMethod(String name,Class<?>...parameterTypes):返回此Class對象對應類的指定方法, 與方法的訪問權限無關。
Method [] getDeclaredMethod():返回此Class對象所表示類的所有public方法。


3、訪問Class對應類所包含的成員變量
Field getField(String name):返回此Class對象對應類的指定public Filed。
Filed[] getField():返回此Class對象對應類的多有public Fileld。
Field getDeclaredField(String name):返回此Class對象對應類指定的Filed,與Field訪問權限無關。
Field[] getDeclaredFields():返回此Class對象對應類的全部Field。




二、用反射生成並操作對象
通過反射來生成對象的兩種方式:
1、使用Class對象的newInstance()方法來創建該Class對象對應類的實例,這種方式要求該Class對象的對應類有默認構造器,而執行newInstance()方法時,實際上是利用默認構造器來創建該類的實例。
2、使用Class對象的newInstance()方法來創建該Class對象對應類的實例,這種方式要求該Class對象的對應類有默認構造器,而執行newInstance()方法時,實際上是利用默認構造器來創建該類的實例。


1、調用方法:
當獲得某個類對應的Class對象後,就可以通過該Class對象的getMethods()方法或者getMethod()方法來獲取全部方法或指定方法——這兩個方法的返回值是Method對象組,或者Method對象。


2、訪問屬性值:
通過Class對象的getFields()或getField()方法可以獲取該類所包括的全部Field(屬性)或指定Field.Field提供瞭如下兩組方法來訪問屬性:


1).getXxx(Object obj):獲取obj對象該Field的屬性值。此處的Xxx對應8個基本類型,如果該屬性的類型是引用類型則取消get後面的Xxx。
2).setXxx(Object  obj,Xxx  val):將obj對象的該Field設置爲val值。此處的Xxx對應8個基本類型,如果該屬性的類型是引用類型則取消set後面的Xxx。


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