線程篇(一):Java中的線程(基礎)

線程和進程的概念

幾乎所有的操作系統都支持進程的概念,所有運行中的任務通常對應一個進程(Process)。當一個程序進入內存運行時,即變成一個進程。進程是處於運行過程中的程序,並且具有一定的獨立功能,進程是系統進行資源分配和調度的一個獨立單位。
多線程則擴展了多進程的概念,使得同一個進程可以同時併發處理多個任務。線程(Thread)也被稱作輕量級進程(Lightweight Process),線程是進程的執行單元。就像進程在操作系統中的地位一樣,線程在程序中是獨立的、併發的執行流。當進程被初始化後,主線程就被創建了。對於絕大多數的應用程序來說,通常僅要求有一個主線程,但也可以在該進程內創建多條順序執行流,這些順序執行流就是線程,每個線程也是相互獨立的。
線程是進程的組成部分,一個進程可以擁有多個線程,一個線程必須有一個父進程。線程可以擁有自己的堆棧、自己的程序計數器和自己的局域變量,但不擁有系統資源,它與父進程的其他線程共享該進程所擁有的全部資源。因爲多個線程共享父進程裏的全部資源,因此編程更加方便;但必須更加小心,因爲需要確保線程不會妨礙同一進程裏的其他線程。

線程的創建和啓動

JAVA多線程實現方式主要有三種:繼承Thread類、實現Runnable接口、使用ExecutorService、Callable、Future實現有返回結果的多線程。其中前兩種方式線程執行完後都沒有返回值,只有最後一種是帶返回值的。

1.繼承Thread類創建線程類

用一個子類繼承Thread,然後在類中重寫run()方法,這個run()方法就是線程要執行的任務。然後再創建這個子類的對象,調用他的start()方法即可開啓該線程。示例如下:
public class FirstThread extends Thread{

	@Override
	public void run()
	{
		for (int i = 0; i < 10 ;i++)
		{
			System.out.println(this.currentThread()+" num:"+i);
		}
	}
	
	public static void main(String[] args){
		FirstThread thread_0 = new FirstThread();
		FirstThread thread_1 = new FirstThread();
		thread_0.start();
		thread_1.start();
	}
}
兩個線程會隨機分配內存運行空間,所以運行結果也是隨機值,其中一次運行結果如下,我們可以看到兩個線程是交替執行的。
Thread[Thread-0,5,main] num:0
Thread[Thread-0,5,main] num:1
Thread[Thread-1,5,main] num:0
Thread[Thread-0,5,main] num:2
Thread[Thread-0,5,main] num:3
Thread[Thread-1,5,main] num:1
Thread[Thread-1,5,main] num:2
Thread[Thread-1,5,main] num:3
Thread[Thread-0,5,main] num:4
Thread[Thread-0,5,main] num:5
Thread[Thread-0,5,main] num:6
Thread[Thread-1,5,main] num:4
Thread[Thread-0,5,main] num:7
Thread[Thread-0,5,main] num:8
Thread[Thread-0,5,main] num:9
Thread[Thread-1,5,main] num:5
Thread[Thread-1,5,main] num:6
Thread[Thread-1,5,main] num:7
Thread[Thread-1,5,main] num:8
Thread[Thread-1,5,main] num:9

2.實現Runnable接口創建子線程

首先定義一個實現Runnable接口的類,重寫run()方法,與上一個實現方式相同,run()方法是該線程的執行體。再創建該類的實例,用這個實例作爲target來創建Thread對象,用Thread對象調用start()方法,即可開啓線程。代碼如下所示:
public class SecondThread implements Runnable{

	@Override
	public void run() {
		for (int i = 0; i < 10; i++) {
			System.out.println(Thread.currentThread() +" num:"+i);
		}
	}
	public static void main(String[] args){
		SecondThread thread_0 = new SecondThread();
		SecondThread thread_1 = new SecondThread();
		new Thread(thread_0).start();
		new Thread(thread_1).start();
	}
}
與線程的第一個實現方式不同,SecondThread只能作爲Thread的target,才能執行線程。運行結果如下:
Thread[Thread-0,5,main] num:0
Thread[Thread-0,5,main] num:1
Thread[Thread-1,5,main] num:0
Thread[Thread-1,5,main] num:1
Thread[Thread-1,5,main] num:2
Thread[Thread-1,5,main] num:3
Thread[Thread-1,5,main] num:4
Thread[Thread-1,5,main] num:5
Thread[Thread-1,5,main] num:6
Thread[Thread-0,5,main] num:2
Thread[Thread-1,5,main] num:7
Thread[Thread-0,5,main] num:3
Thread[Thread-0,5,main] num:4
Thread[Thread-1,5,main] num:8
Thread[Thread-0,5,main] num:5
Thread[Thread-0,5,main] num:6
Thread[Thread-0,5,main] num:7
Thread[Thread-0,5,main] num:8
Thread[Thread-1,5,main] num:9
Thread[Thread-0,5,main] num:9

3.使用Callable和Future創建有返回值的線程

使用Callable和Future我們可以創建一個帶有返回值的線程,我們基本上很少使用這種方式。在Android中更是很少,因爲在獲取子線程的返回值的時候,會阻塞當前線程,違反我們使用線程的目的。下面我們來說一下這種線程的使用方式,分以下幾個步驟:
1、創建一個Callable的實現類,並實現它的call()方法。
2、用FutureTask來包裝Callable對象,創建FutureTask的對象task。
3、把FutureTask對象task作爲Thread的target,創建一個Thread對象,並開啓線程。
4、用task.get()獲取子線程的返回值。注意調用該方法時,會阻塞當前線程,直到獲取到子線程的返回值。
public class ThirdThread {
	public static void main(String[] args)
	{
		
		FutureTask<Integer> task = new FutureTask<Integer>(new Callable<Integer>() {
			@Override
			public Integer call() throws Exception {
				int i = 0;
				for (;i<10;i++)
				{
					System.out.println(Thread.currentThread() + " num:"+i);
				}
				return i;
			}
		});
		Thread thread = new Thread(task);
		thread.start();
		
		for (int j = 0;j < 10; j++)
		{
			System.out.println(Thread.currentThread() + " num:"+j);
		}
		
		try {
			System.out.println("子線程的返回值:" +  task.get());
		} catch (Exception e) {
			System.out.println("錯誤的提示e" + e);
		}
	}
}
打印結果如下:
Thread[main,5,main] num:0
Thread[main,5,main] num:1
Thread[main,5,main] num:2
Thread[main,5,main] num:3
Thread[main,5,main] num:4
Thread[Thread-0,5,main] num:0
Thread[Thread-0,5,main] num:1
Thread[main,5,main] num:5
Thread[Thread-0,5,main] num:2
Thread[Thread-0,5,main] num:3
Thread[Thread-0,5,main] num:4
Thread[Thread-0,5,main] num:5
Thread[Thread-0,5,main] num:6
Thread[Thread-0,5,main] num:7
Thread[Thread-0,5,main] num:8
Thread[Thread-0,5,main] num:9
Thread[main,5,main] num:6
Thread[main,5,main] num:7
Thread[main,5,main] num:8
Thread[main,5,main] num:9
子線程的返回值:10
其中Thread[main,5,main]代表的是主線程,java程序在進入main()方法的時候,就已經創建的一個線程,這個線程就是主線程。獲取子線程的返回值的方法需要使用try-catch包裹。
以上是三種線程的基本使用方式。該篇爲Java的線程基礎篇,只是爲Android線程入門。所以更深的Java線程知識,之後再補充。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章