天天看點

Java多線程之線程的建立、優先級程序線程

Java多線程

  • 程序
  • 線程
    • 線程的生命周期
    • 建立線程
    • 線程的優先級
    • 線程排程器

程序

正在運作中的程式。每個程序都擁有自己(獨立)的系統資源、記憶體空間和位址空間

線程

線程是作業系統能夠進行運算排程的最小機關,它被包含在程序之中,是程序中的實際運作機關。

線程的生命周期

建立狀态(new )、可運作狀态(runnable)、運作狀态(running )、阻塞狀态(blocked)、終止狀态(dead)
  1. 當線程處于建立狀态的時候,表明此時線程的對象執行個體已經被建立,但是尚未取得運作線程所需要的資源
  2. 産生了對象的執行個體之後,一旦調用線程的start()方法,則線程就會進入可運作狀态,表明該線程已經獲得運作時所需要的系統資源,具備了被排程執行的條件,進而使該線程可以被排程執行。
  3. 線程的運作狀态是指線程被JVM線程排程程式配置設定了CPU執行時間,使用run() (在執行了start()之後,,run()自啟動)方法可以使線程進入運作狀态。正在運作的線程随時可能由JVM線程排程程式送回可運作狀态。
  4. 當線程的run()方法執行完畢後進入終止狀态,處于該狀态的線程不會再被排程執行。
  5. 阻塞狀态通常用于線程之間的通信與同步控制。

建立線程

Java程式中的線程被設計為一個對象,該對象具有自己的生命周期,可以利用接口java.lang.Runnable、類java.lang.Thread、Callable接口 建立一個線程

通過java.lang.Thread建立線程

繼承Thread類,重寫 run() 方法(必須重寫)

public class ThreadDemo extends Thread {
 
    @Override
    public void run() {
        System.out.println("目前線程的是:"+this.getName());
    }
 
    public static void main(String[] args) {
        ThreadDemo threadDemo = new ThreadDemo();
        threadDemo.start();
    }
 
}
           
  • 優點:程式代碼相對簡單,缺點:java 單繼承使用場景限制

實作Runnable接口,實作 run() 方法

public class RunnableDemo implements Runnable {
 
    @Override
    public void run() {
        System.out.println("目前線程的是:"+Thread.currentThread().getName());
    }
 
    public static void main(String[] args) {
        RunnableDemo runnableDemo = new RunnableDemo();
        new Thread(runnableDemo).start();
   	 }
    }
 
           

Runnable建立線程:通過把Runnable的一個子類的執行個體作為參數傳遞 給Thread類的一個構造方法

優點:

  1. 符合面向對象的設計思想
從面向對象的設計角度看,Thread類是虛拟CPU 的封裝,因而Thread類的子類是關于CPU行為的類,但是在繼承Thread類的子類大多都是與CPU不相關的類,而實作Runnable接口的方法将不會影響到Thread體系
  1. 實作了Runnable接口的類可以 用extends繼承其他的類

Callable接口建立線程:實作Callable 接口,使用FutureTask 進行包裝,通過Thread的構造方法傳入futureTask執行個體

package com.callable;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class ICallableTest implements Callable<Long> {
    @Override
    public Long call() {
        Long id = Thread.currentThread().getId();
        System.out.println("目前的線程是"+Thread.currentThread().getName());
        return id;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ICallableTest ct = new ICallableTest();
        FutureTask futureTask = new FutureTask(ct);
        Thread t = new Thread(futureTask,"二貨");
        t.start();
        System.out.println(futureTask.get());
    }
}

           

實作Callable接口的 call() 方法是帶傳回值(方法體中必須return )的,通過futureTask的 get() 獲得

Java多線程之線程的建立、優先級程式線程

Callable和Runnable 的差別:

  • Runnable的 run() 方法沒有傳回值,而Callable得 call() 方法有傳回值,且支援泛型
  • Runnable 接口 的 run() 方法隻能抛出運作時候得異常,且無法捕獲處理;Callable 接口 call 方法允許抛出異常(throws Exception),可以擷取異常資訊

線程的優先級

線程優先級是指優先級越高,越有可能先執行,但隻是建議先執行,具體什麼時候執行由系統決定(既不能絕對的說線程的排程是按照優先級進行排程的)

例如在windows系統中,當一個優先級為5且處于可運作狀态的線程在等待CPU資源的時,系統可能正在執行一個優先級為3的線程
  • 設定線程的優先級
public final void setPriority(int newPriority) ;
           
  • 擷取線程的優先級
public final int getPriority( );
           
  • 在Thread 類中定義了線程優先級的取值範圍(1~10)
//靜态成員變量
  	public static final int MIN_PRIORITY = 1;


    public static final int NORM_PRIORITY = 5;


    public static final int MAX_PRIORITY = 10;
           

優先級高隻是建議先執行

Priority.java

public class Priority extends Thread {
    public Priority(String s){
        setName(s);
    }
    public void run(){
        System.out.println("線程:"+getName()+"----"+getPriority());
    }
}

           

PriorityTest.java

public class PriorityTest {
    public static void main(String[] args){
        Priority p1 = new Priority("線程 1");
        Priority p2 = new Priority("線程 2");
        Priority p3 = new Priority("線程 3");
        Priority p4 = new Priority("線程 4");
        p1.setPriority(1);
        p2.setPriority(2);
        p3.setPriority(3);
        p4.setPriority(4);
        p1.start();
        p2.start();
        p3.start();
        p4.start();
    }
}

           
Java多線程之線程的建立、優先級程式線程
Java多線程之線程的建立、優先級程式線程

線程排程器

Java提供了一個線程排程器來監視所有程式中的所有運作的線程,并決定哪個線程應該運作,哪個線程應該排隊等待。線上程的 排程器的決策過程中,它可以識别線程的兩個特征:一個是線程的優先級别,另一個是守護标志
  • 守護線程:一般具有一個較低的優先級别,并且當計算機中運作的線程減少的時,為一個或多個程式提供一項基本的服務。例如垃圾收集線程就是一個不斷運作的守護線程,它由于JVM提供,通過掃描程式查找不再被通路的變量,并把這些變量的資源釋放給系統
  • 排程器的基本原則:如果隻有守護線程在運作,JVM将退出。新線程将從建立它的線程那裡繼承優先級别和守護标志,排程器通過分析所有線程的優先級來決定哪個線程先運作。具有較高優先級的線程,能夠在較低優先級的 線程之前執行(但并不絕對)。