Java之線程基礎

簡介

  本文主要介紹Java編程中線程的基礎知識,包括線程介紹、線程的五大狀態、線程的三種創建方式、線程的同步,最後根據線程的經典問題——生產者消費者模型,給出了實現的源代碼。
  通過本文的學習,可以掌握基本的Java多線程編程。

一、線程介紹

   若將操作系統中的任務看成進程,那麼任務中的多個執行流可以看做是多個線程。
  進程是系統進行資源分配和調度的一個獨立單元。
  線程是進程的組成部分,一個進程可以擁有多個線程,一個線程必須有一個父進程。線程可以擁有自己的堆棧、自己的程序計數器和自己的局部變量,但不擁有系統資源,它與父進程的其他線程共享該進程所擁有的全部資源。

二、線程的五大狀態

  每個線程都有自己的生命週期,通常將生命週期分爲5個狀態(階段),即新建(New)、就緒(Ready)、運行(Running)、阻塞(Blocked)、死亡(Dead)。

1、新建狀態

  當使用new關鍵字新創建一個Thread對象時,該線程就進入了新建狀態。JVM會爲新建的線程分配內存、並初始化線程對象的成員變量,線程對象的執行體還未啓動。

2、就緒狀態

  當一個線程對象執行了start()成員方法時,該線程便進入了就緒狀態。JVM開始爲線程對象創建方法調用棧和程序計數器。此時線程對象同樣沒有運行,只代表線程對象可以運行,運行時機取決於JVM的線程調度器。

3、運行狀態

   當JVM調度器調度就緒狀態的線程對象時,即執行線程對象的run()方法,那麼該線程對象進入了運行狀態。
  對於單個處理器中存在多個線程時,處理器採用時間片輪換的方式來執行各個線程。

4、阻塞狀態

  爲了使多個線程都可到執行,那麼處於運行狀態的線程對象不可能一直處於運行狀態。當被中斷時,線程對象從運行狀態變爲了阻塞狀態。
  線程進入阻塞狀態的情況:

  •   遇到 sleep();
  •   遇到 join();
  •   遇到 wait();
  •   遇到 read()、write();

5、死亡狀態

  當線程生命週期結束時,線程對象便進入了死亡狀態,進入死亡狀態的線程不能重進入其它任何狀態,只能靜靜等着JVM垃圾回收機制來回收自己。

三、線程的三種創建方式

  JDK中提供了三種創建線程對象的方式,如繼承Thread、實現Runnable、實現Callable。

1、繼承Thread

  線程對象類直接繼承Thread類,並重寫Thread類的run()方法。如下所示:

public class ThreadTest extends Thread{
	@Override
	public void run() {
		// 執行體代碼
	}	
}

  該線程對象的運行,如下所示:

public static void main(String[] args) {
	Thread thread01 = new ThreadTest();
	thread01.start();	
}

2、實現Runnable

  Runnable是一個接口,線程對象類可以實現該接口,並重寫Runnable接口的run()方法。如下所示:

public class ThreadTest implements Runnable{
	@Override
	public void run() {
		// 執行體代碼
	}	
}

  該線程對象的運行,如下所示:

public static void main(String[] args) {
	ThreadTest thread01 = new ThreadTest();
	new Thread(thread01, "Thread-name").start();	
}

3、實現Callable

  實現Callable接口的線程,創建過程如下:

  •   1.創建一個線程,創建Callable的實現類Race,並且重寫call方法;
  •   2.得到Future對象;
  •   3.獲取返回值;
  •   4.停止服務;
//返回Interger類型
public class ThreadTest implements Callable<Integer>{
	@Override
	public Integer call() {
		//執行體代碼
		return Integer;
	}
}

  該線程對象的運行,如下所示:

public static void main(String[] args) {
	ExecutorService ser = Executors.newFixedThreadPool(2);		
	ThreadTest threadTest = new ThreadTest();			
	//獲取值
	Future<Integer> result = ser.submit(threadTest);
		
	try {
		int numR = result.get();
	} catch (InterruptedException e) {
		e.printStackTrace();
	} catch (ExecutionException e) {
		e.printStackTrace();
	}
		
	//停止服務
	ser.shutdown();
}

四、線程的同步

  在多線程的情況下,會存在對公共資源進行訪問的行爲,也就是資源的競爭關係,其中同步就是多線程編程中處理競爭關係的一種方法,它使多線程訪問公共資源時是安全有效的。同步使用synchronized關鍵字,其中又分爲synchronized方法synchronized塊

1、synchronized方法

  用synchronized關鍵字修飾類的一個方法,如下所示:

public synchronized void seats() {
	//需要同步的對象屬性操作代碼
}

  用synchronized關鍵字修飾的一個作用塊,如下所示:

synchronized(ThreadTest.class) {
	//需要同步的對象屬性操作代碼
}

五、生產者消費者實例

  多線程編程中,最經典的問題就是生產者消費者問題:
  生產者負責生產產品,消費者購買產品,當庫存爲空的時候,生產者繼續生產,消費者購買數量要小於等於庫存上限,不能出現,生產一次,消費兩次,或者生產了沒有消費的情況。
  我的代碼實現如下:

import java.util.ArrayList;
import java.util.List;

public class Cooperation {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		PipeHandle pipe = new PipeHandle();
		
		Productor productor = new Productor(pipe);
		Customer customer = new Customer(pipe);
		
		new Thread(productor,"Productor").start();
		new Thread(customer,"Customer").start();
	}
}

//生產者
class Productor implements Runnable{
	PipeHandle pipe;
	
	public Productor(PipeHandle pipe) {
		super();
		this.pipe = pipe;
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		for(int i=0; i < 100; i++) {
			Food food = new Food();
			pipe.push(food);
			System.out.println("Productor is making " + i +" food");
		}
	}
	
}
//消費者
class Customer implements Runnable{
	PipeHandle pipe;
	
	public Customer(PipeHandle pipe) {
		super();
		this.pipe = pipe;
	}
	
	@Override
	public void run() {
		// TODO Auto-generated method stub
		for(int i=0; i < 100; i++) {
			Food food = pipe.pop();
			System.out.println("Coustomer is get "+i+" food");
		}
	}
	
}

//商品緩存區管道
class PipeHandle{
	Food[] pipe = new Food[10];
	int count;
	public PipeHandle( ) {
		
	}
	
	public synchronized void push(Food food) {
		if(count >= 10) {
			try {
				this.wait();
			} catch (InterruptedException e) {
			
			}
		}
		
		pipe[count++] = food;
        this.notifyAll();
	}
	
	public synchronized Food pop() {
		Food food = null;
		if(count == 0) {
			try {
				this.wait();
			} catch (InterruptedException e) {
			
			}
		}
		
		food = pipe[--count];
		this.notifyAll();

		return food;
	}
}

//商品
class Food{
	
}
發佈了21 篇原創文章 · 獲贊 0 · 訪問量 1823
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章