1. 程式人生 > >多執行緒1

多執行緒1

//程式就是[可執行]的檔案
//程式執行起來就是一個程序
//執行緒是程序的最基本單位
//只要有程序,就最少有一個執行緒
//CPU線上程上幹活
/*
 * 多執行緒:
 * 
 * 程式:是一個可執行的檔案.
 * 程序:是一個正在執行的程式.在記憶體中開闢了一塊兒空間
 * 執行緒:負責程式的執行,可以看做程式執行的一條通道或者一個執行單元.所以我們通常將程序的工作理解成執行緒的工作.
 * 
 * 程序中可不可以沒有執行緒?  必須有執行緒,至少有一個,當有一個執行緒存在的時候,我們稱為單執行緒,這個唯一的執行緒就是主執行緒(main執行緒)
 * 		   					當有兩個及講個個以上的執行緒存在的時候,我們稱為多執行緒.
 * 
 * 多執行緒存在的意義:為了實現同一時間做多件事情.
 * 
 * 任務區:我們將執行緒完成工作的方法稱為任務區。其實任務區就是run()方法
 * 每一個執行緒都有自己的任務區
 * 
 * JVM是多執行緒嗎?
 * 一定是多執行緒
 * 至少有兩個
 * 主執行緒的任務區:main方法
 * 垃圾回收執行緒的任務區:finalize()方法
 */


public class Demo7 {

	public static void main(String[] args)//--有一個執行緒:主執行緒 
	{
		new MyTest();//匿名物件---垃圾
		/*
		 * 手動執行gc:垃圾回收器,執行垃圾回收機制。
		 * 
		 * 原理:當執行gc方法時,會觸發垃圾回收機制,開啟垃圾回收執行緒,自動呼叫finalize方法
		 */
		//注意點:多個執行緒之間是搶cpu的關係,cpu有隨機性
		System.gc();//有兩個執行緒
		System.out.println("main");
	}//主函式結束,主任務區結束,執行緒隨著任務的結束而結束,隨著任務的開始而開始,
	//main()相當於開啟主執行緒,並執行裡面的程式(任務)
	//當執行緒還在工作的時候,程序不能結束

}
class MyTest{
	//重寫finalize
	/*
	 * 正常情況下,這個函式是由系統自動呼叫的,重寫它是為了觀察多執行緒的實現
	 * 正常情況下,當MyTest的物件被釋放的時候,會自動呼叫他的finalize方法
	 */
	protected void finalize()throws Throwable{
		//正常的這裡其實有父類的方法...進行垃圾回收
		System.out.println("finalize");
	}
}
/*
 * 預設情況下,主執行緒和垃圾回收執行緒都是由系統建立的,但是我們需要完成自己的
 * 功能---所以要建立自己的執行緒物件。
 * java將執行緒面向物件了,形成的類就是Thread,在Thread類內部執行任務的方法叫run()
 * 注意:如果想要run作為任務區,必須讓他去被自動呼叫,我們通過執行start方法,來實現run()方法的呼叫
 * 其實呼叫start()方法相當於開啟這個執行緒,start方法會自動呼叫run()方法,相當於在該執行緒上跑任務(run方法內的程式)
 */
public class Demo8 {

	public static void main(String[] args) {//兩個。垃圾回收執行緒和主執行緒,
		//注:一般會將垃圾回收執行緒忽略掉
		
//		//1.通過Thread類直接建立執行緒
//		Thread中的run()裡並沒有任何程式碼
//		Thread t1=new Thread();
//		Thread t2=new Thread();
//		//呼叫start(),開啟執行緒
//		t1.start();//此時有兩個執行緒
//		t2.start();//此時有三個執行緒
//		System.out.println("main");
		
		
		//2通過Thread類的子類建立執行緒
		MyThread t1=new MyThread("xiaote");//建立了一個執行緒 thread-0
		MyThread t2=new MyThread("xiaosan");//建立了一個執行緒 thread-1
		//呼叫start(),開啟執行緒
		t1.start();//此時有兩個執行緒
		t2.start();//此時有三個執行緒
		System.out.println("main");
		for(int i=1;i<=10;i++) {
			System.out.println(Thread.currentThread().getName()+" "+"  i:  "+i);

		}
		//手動呼叫run方法,它只是一個普通的方法,沒有開啟執行緒,只是在主執行緒中跑完了run方法裡的內容
		t1.run();
	}
}


//寫	Thread類的子類,因為Thread類的run()方法是空的,無法實現具體的任務,
//所以用建立子類的方式去實現我們自己的功能,作為Thread子類也是執行緒類
class MyThread extends Thread{
	String myname;
	/*
	 * 重寫run()方法作為執行緒的任務區,完成我們的功能
	 * Thread.currentThread()獲取的是當前的任務區所線上程的物件
	 * getName():獲取執行緒的名字
	 */
	public MyThread(String myname) {
		this.myname=myname;
	}
	public void run() {
		for(int i=1;i<=10;i++)
		{	
			System.out.println(Thread.currentThread().getName()+" "+myname+"  i:  "+i);
		}
	}
	
}

//------下面兩個例子還沒有弄好

/*
 * 例項:四個售票員賣票
 * 分析:建立4個執行緒--四個售票員
 * 	一份資料
 * 實現多執行緒的兩種方式:
 * 第一種方式:通過建立Thread子類的方式實現功能---執行緒與任務繫結在了一起
 * 第二種:將任務從執行緒中分離出來,哪個執行緒需要工作,就將任務交給誰,操作方便
 *
 */

//第一種方式:通過建立Thread子類的方式實現功能---執行緒與任務繫結在了一起
public class Demo9 {

	public static void main(String[] args) {
//		//建立四個執行緒
//		Seller s1=new Seller();
//		Seller s2=new Seller();
//		Seller s3=new Seller();
//		Seller s4=new Seller();
//		
//		//開啟執行緒
//		s1.start();
//		s2.start();
//		s3.start();
//		s4.start();


		
//第二種:將任務從執行緒中分離出來
		//1先建立任務類物件
		Ticket ticket=new Ticket();
		//2建立執行緒物件,並將任務交給執行緒
		Thread t1=new Thread(ticket);
//裡面自帶一個run()然後Ticket裡也有一個run()
//如果有Runnble的run方法,就會執行Runnale的run方法
//沒有Thread中的裡面什麼都沒有的run()方法
//所以說明任務類中的run方法優先順序高於Thread內部的run()

		Thread t2=new Thread(ticket);
		Thread t3=new Thread(ticket);
		Thread t4=new Thread(ticket);
		//3開啟執行緒
		t1.start();
		t2.start();
		t3.start();
		t4.start();
	}
}
//建立任務類
class Ticket implements Runnable{
	//所有的物件共享num
	int num=40;
	@Override
	public void run() {
		for(int i=0;i<10;i++) {
			System.out.println(Thread.currentThread().getName()+"  "+i+" "+(--num));
		}
	}
	
}
		
//建立Thread的子類
//class Seller extends Thread{
//	//所有的物件共享num
//	static int num=20;
//	public void run() {
//		for(int i=0;i<5;i++) {
//			System.out.println(Thread.currentThread().getName()+"  "+i+" "+(--num));
//		}
//		}
//	}
public class Demo10 {

	public static void main(String[] args) {
		//執行緒的其他知識點
		//1
		Thread t1=new Thread();
		Thread t2=new Thread(t1);
		//將t2當做任務處理了,因為Thread實現了Runable介面
		t1.start();//呼叫的是t1的run()方法
		t2.start();//呼叫的也是t1的run()方法
		
		//2匿名子類物件也可以工作
		new Thread();//匿名物件
		new Thread() {
			public void run() {}
			//這裡重寫了run()但其實Thread類本身裡面就有run(){}
		}.run();//匿名子類物件,該物件的父類是Thread
		//直接呼叫run()沒有用開啟執行緒,這裡run()就是普通的方法
		
		//正確的方式:
		new Thread() {
		public void run() {}
		//這裡重寫了run()但其實Thread類本身裡面就有run(){}
		}.start();
	}
	
}