併發與並行,進程與線程不只是操做系統中及其重要的概念,也是併發編程入門 java
必需要理解的核心知識。 web
順序編程:程序中的全部事物在任意時刻都只能執行一個步驟 編程
併發:在同一時間段內,須要處理多個任務,而在每一個時間點又只能處理一個,這就是併發。 安全
假設咱們要把多個任務分配給處理機,若是這臺機器有多個處理器,顯然能夠同時執行這些任務,這就是並行。 多線程
不一樣於並行,併發的目的旨在最大限度的提升程序在單處理器上的效率。前者是在物理上的同時發生,而併發是在邏輯上的同時發生。如圖,若是要在同一個時間段內處理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多線程對於線程的建立有了初步的瞭解。在本系列的後續部分將會繼續探討併發編程中的細節。
若是以爲本文對您有所幫助的話,就給俺點個贊吧~