走近併發編程之一 進程和線程

併發與並行,進程與線程不只是操做系統中及其重要的概念,也是併發編程入門 java

必需要理解的核心知識。 web

  1. 什麼是併發?併發與並行的區別

順序編程:程序中的全部事物在任意時刻都只能執行一個步驟 編程

併發:在同一時間段內,須要處理多個任務,而在每一個時間點又只能處理一個,這就是併發。 安全

假設咱們要把多個任務分配給處理機,若是這臺機器有多個處理器,顯然能夠同時執行這些任務,這就是並行多線程

不一樣於並行,併發的目的旨在最大限度的提升程序在單處理器上的效率。前者是在物理上的同時發生,而併發是在邏輯上的同時發生。如圖,若是要在同一個時間段內處理task1, task2,須要在任務之間來回切換,完成併發執行 併發

圖:一個簡單併發的例子 負載均衡

 

    2.  Java的多線程和併發性 分佈式

Java是一種多線程語言,併發是Java很是重要的高級特性之一。對於分佈式系統甚至於web系統的開發者來講,學會高效的併發編程相當重要。例如,web系統是Java的常見應用之一,最基本的java web庫類 Servlet就具有天生的多線程特性,圖形用戶界面相似於Swing和SWT也具有線程安全的機制。若是你不瞭解併發,你很難很好的使用好這些工具。 函數

 

    3.  進程和線程 工具

進程能夠定義爲一個執行中的程序的實例,進程擁有本身的地址空間,以及用來記錄進程的進程控制塊(PCB)。想到實現併發,人們最早想到的即是經過進程。在多任務操做系統中,CPU會週期性地從一個進程切換到另外一個進程。這種實現方式很是理想化,因爲不一樣進程處於不一樣的地址空間,彼此之間不會干涉,這使得實現起來更爲容易。

惋惜的是,雖然具備以上優勢,但因爲進程一般都會有開銷和數量的限制,想要使用進程來併發編程顯然不夠經濟。

圖:進程的開銷( 任務管理器)

 

函數型語言能夠將併發任務彼此隔離,這種專門的併發語言爲處理大量併發任務提供了方便。

線程是在單一進程中建立的任務,線程與線程之間共享進程的地址空間和內存資源,Java的併發就是在順序語言的基礎上引入線程機制,經過多線程 之間的協做來實現併發。

多線程併發的好處是能夠共享資源,開銷較小,然而同時也使得系統的複雜性增長。不過與程序設計的方便性,資源的負載均衡實現相比,複雜性代價也變得微不足道了。

 

    4.  線程的建立

Java中建立線程,常常用到java.lang.Thread類,以下建立一個線程:

Thread thread  = new Thread();

 

調用start()方法啓動線程

thread.start();

 

因爲咱們沒有繼承Thread類,重載Thread的run()方法,因此在start()以後線程沒有任何動做。

要想讓線程執行咱們想要它完成的任務,還須要建立Thread的子類來重載run()方法。

 

    5.  建立Thread子類

舉個栗子

public class MyThread extends Thread {

    public void run(){

        System.out.println("ACFLOOD!");

    }

}

 

經過以下代碼來運行MyThread

MyThread myThread = new MyThread();

myThread.start();

 

    6.  實現Runnable接口

咱們還能夠經過實現Runnable接口來實現run()方法,你可能會問,Runnable和Thread的區別是什麼? 其實,在Java的多線程機制中,Runnable的實現就至關於一個Task,也就是咱們想讓線程完成的任務。Thread的目的是用來驅動這些任務,咱們想要執行Task,只須要把Runnable的實例放入Thread中。好比下面的倒計時任務LiftOff

public class LiftOff implements Runnable {

  protected int countDown = 10; //Default

  private static int taskCount = 0;

  private final int id = taskCount++;

 

  public LiftOff(){}

  public LiftOff(int countDown){

      this.countDown = countDown;

  }

 

  public String status() {

      return "#" + id  + "(" + (countDown > 0 ? countDown : "LiftOff!")+").";

  }

 

  public void run(){

      while(countDown-- > 0){

        System.out.print(status());

        Thread.yield(); //對線程調度的建議

    }

  }

}

 

 

咱們能夠直接調用run()方法來執行。此時程序依舊是順序執行,即只有主線程在運行,並無新的線程被建立。

public class MainThread {

    public static void main(String[] args){

        LiftOff launch = new LiftOff();

        laucn.run();

    }

}

 

更好的辦法是交給Thread類來調度

public class BasicThreads{

     Thread t = new Thread(new LiftOff());

     t.start();

     System.out.println("Waiting for LiftOff");       

}

 

在這個例子中,start()方法執行以後返回,以後輸出main()主線程中的waiting for liftoff,run()在另外一個線程最後執行完成。

 

    7.  總結

經過本文的學習,相信讀者對併發的基本概念,併發基本的實現原理,以及java多線程對於線程的建立有了初步的瞭解。在本系列的後續部分將會繼續探討併發編程中的細節。

 

若是以爲本文對您有所幫助的話,就給俺點個贊吧~

相關文章
相關標籤/搜索