天天看點

Java多線程(一)——Thread基礎

#

Java多線程(一)——Thread基礎

##一、Thread概述

一個正在運作的應用程式,就是一個程序,程序是系統配置設定資源的最小機關,擁有獨立的堆棧空間和資料段,程序之間彼此獨立,不能互相控制,安全性高,必須通過程序間通信機制來進行通路,系統每開辟一個程序都要較大的系統開銷。

而線程是程序中的一個任務,一個程序可以擁有多個線程,線程是程序中的最小運算執行單元。線程擁有獨立的棧空間和獨立的PC寄存器,但是共享程序的堆空間資料,開銷較小。單個程序内的所有線程都具有同等地位,程序内的任何線程都可以建立,銷毀,挂起,休眠,恢複其他線程和更改其優先級。

重要的概念:

  • 并行:多個CPU或者多台機器在同時處理不同的任務,是實體上的同時發生
  • 并發:單個CPU在不同的任務之間通過CPU排程算法來回切換,讓使用者看上去多個任務是在同時進行,是邏輯上的同時發生
Java多線程(一)——Thread基礎

上圖很好的闡述了并發與并行的差別,Java中的多線程是一種并發程式設計。

  • 線程安全:由于Java多程式設計是一種并發程式設計,這就涉及到多個線程通路程序中共享資料時的資料安全問題,在之後的Java多線程記憶體模型中會詳細講述。線程安全含義是在并發程式設計中,線程的排程順序不影響最終結果。
  • 同步:即多線程串行通路一個資料或一段代碼,保證在同一時間隻有一個線程在進行通路這個資料或代碼段。同步保證了多線程并發的安全性,但是性能相對會降低。在Java中通常使用synchronized關鍵字來保證線程的同步
  • 異步:即多線程并行同時處理某個任務,異步擁有更好的性能,但是不保證線程的安全性

##二、Thread的建立方式

在Java中建立Thread的方式有三種,分别是通過繼承java.lang.Thread類,實作java.lang.Runnable接口以及實作java.util.concurrent.Callable接口。第三種涉及線程池的概念,将放線上程池的文章中講述,這裡不再描述。前兩種方式都是建立Thread類的對象,需要調用start()方法來啟動該線程。

####方式一:繼承java.lang.Thread類

當一個線程進入運作狀态後,就會調用Thread類的run方法,是以這裡我們可以通過繼承的方式來重寫Thread中的run方法,來實作我們想要的功能。

public class MyThread extends Thread{

	@Override
	public void run() {
		int i = 0;
		while(i < 20) {
			System.out.println("MyThread:" + i);
			i++;
		}
	}

	public static void main(String[] args) {
		
		MyThread myThread = new MyThread();
		myThread.start();

		int i = 0;
		while(i < 20) {
			System.out.println("MainThread:" + i);
			i++;
		}
	}
}
           

運作結果如下:

MainThread:0
MyThread:0
MainThread:1
MainThread:2
MyThread:1
MainThread:3
MyThread:2
MyThread:3
MyThread:4
MyThread:5
MyThread:6
MyThread:7
MyThread:8
MyThread:9
MyThread:10
MyThread:11
MyThread:12
MyThread:13
MainThread:4
MainThread:5
MainThread:6
MyThread:14
MyThread:15
MyThread:16
MyThread:17
MainThread:7
MyThread:18
MainThread:8
MainThread:9
MainThread:10
MainThread:11
MainThread:12
MainThread:13
MainThread:14
MainThread:15
MainThread:16
MainThread:17
MainThread:18
MainThread:19
MyThread:19
           

####方式二:實作java.lang.Runnable接口

Runnable接口中隻有一個run()方法,在建立Thread對象時,可以傳入一個實作Runnable接口的匿名内部類,實作run方法,那麼在運作該線程時,就會優先調用傳入的Runnable中的run方法。

public class MyThread {

	public static void main(String[] args) {
		
		Thread myThread = new Thread(new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				int i = 0;
				while(i < 20) {
					System.out.println("MyThread:" + i);
					i++;
				}
			}
		});
		myThread.start();

		int i = 0;
		while(i < 20) {
			System.out.println("MainThread:" + i);
			i++;
		}
	}
}
           

上述兩種方式建立線程沒有什麼差別,但是一般一個類隻有在其需要被加強或者修改時才會被繼承,是以這裡推薦使用第二種方式來建立線程

繼續閱讀