Java第二十天

    1. 程序和進程

程序就是一堆靜態的代碼,存儲在硬盤上。程序若是不運行,本質就是一個文件。java

程序一次運行產生進程,進程一直向前運行,直到進程結束。安全

  1. 操做系統的發展

單任務操做系統:一段時間只能運行一個程序(任務)。CPU利用率很是低。多線程

 

引入進程的概念併發

把程序的一次運行產生進程(內存空間、資源、程序的執行堆棧)ide

 

進程做爲操做系統分配資源的基本單位。this

 

多任務操做系統spa

一臺電腦就一個CPU,多個任務輪流使用CPU,從宏觀上看,一段時間有多個任務正在運行。操作系統

從微觀上看,一個時間點只有一個任務在運行。.net

 

CPU時間片線程

多個進程經過CPU時間片輪轉實現多任務(進程)。把這種現象叫作併發操做

 

並行:

一個時間段,多個任務同時進行,多個CPU運行各自的進行。

 

線程的引入

解決實時性問題

 

  1. 進程和線程區別

 

綜合性案例

 

  1. 多線程實現

Thread 類位於java.lang中,表示進程中的執行線程。實現多線程有兩種方式
 

繼承Thread和實現Runnable接口實現多線程的優缺點

[1] 繼承Thread的線程類不能再繼承其餘類,實現Runnable接口的類還能夠繼承其餘類。

[2] 實現Runnable接口的線程類,可讓多個線程共享線程實現類的資源

 

  1. 線程的生命週期

新生狀態

用new關鍵字創建一個線程後,該線程對象就處於新生狀態。

處於新生狀態的線程有本身的內存空間,經過調用start()方法進入就緒狀態。

 

就緒狀態

處於就緒狀態線程具有了運行條件,但還沒分配到CPU,處於線程就緒隊列,等待系統爲其分配CPU。

當系統選定一個等待執行的線程後,它就會從就緒狀態進入執行狀態,該動做稱爲「CPU調度」。

運行狀態

在運行狀態的線程執行本身的run方法中代碼,直到等待某資源而阻塞或完成任何而死亡。

若是在給定的時間片內沒有執行結束,就會被系統給換下來回到等待執行狀態。

阻塞狀態

處於運行狀態的線程在某些狀況下,如執行了sleep(睡眠)方法,或等待I/O設備等資源,將讓出CPU並暫時中止本身運行,進入阻塞狀態。

在阻塞狀態的線程不能進入就緒隊列。只有當引發阻塞的緣由消除時,如睡眠時間已到,或等待的I/O設備空閒下來,線程便轉入就緒狀態,從新到就緒隊列中排隊等待,被系統選中後從原來中止的位置開始繼續執行。

死亡狀態

死亡狀態是線程生命週期中的最後一個階段。線程死亡的緣由有三個,一個是正常運行

的線程完成了它的所有工做;另外一個是線程被強制性地終止,如經過stop方法來終止一個

線程【不推薦使用】;三是線程拋出未捕獲的異常。

 

 

 

  1. 線程經常使用方法
    1. [1]線程優先級

public static void main(String[] args) {

        

         System.out.println(Thread.MIN_PRIORITY);

         System.out.println(Thread.MAX_PRIORITY);

         System.out.println(Thread.NORM_PRIORITY);

        

         //主線程的優先級(默認優先級)

         System.out.println(Thread.currentThread().getPriority());

        

        

         Thread01 t1 = new Thread01();

         // 設置線程的優先級

         t1.setPriority(Thread.MAX_PRIORITY);

         t1.start();

        

        

         Thread01 t2 = new Thread01();

         // 設置線程的優先級

         t2.setPriority(Thread.MIN_PRIORITY);

         t2.start();

        

        

     }

線程優先級高,被cpu調度的機率大,不表示必定先運行。

 

  1. [2]isAlive

判斷線程是否處於活動狀態。

         Thread01 t1 = new Thread01();

         System.out.println(t1.isAlive());

         // 設置線程的優先級

         t1.setPriority(Thread.MAX_PRIORITY);

         t1.start();

         System.out.println(t1.isAlive());

線程調用start以後就處於活動狀態。

 

  1. [3]join

調用該方法的線程強制執行,其它線程處於阻塞狀態,該線程執行完畢後,其它線程再執行

join稱爲線程的強制執行,有可能被外界中斷產生InterruptedException 中斷異常。

 

public class Test02 {

     public static void main(String[] args){

        

         Thread02 t = new Thread02("線程A");

         t.start();

        

         for (int i = 0; i < 5; i++) {

             

              if(i == 2) {

                   try {

                       t.join();

                   } catch (InterruptedException e) {

                       e.printStackTrace();

                   }

              }

             

              System.out.println(Thread.currentThread().getName() + "->" + i);

         }

     }

}

 

  1. [4]sleep()

在指定的毫秒數內讓當前正在執行的線程休眠(暫停執行)。休眠的線程進入阻塞狀態。

public static void main(String[] args) {

       

        Thread03 t = new Thread03("線程A");

        t.start();

       

        Thread mainThread = Thread.currentThread();

        System.out.println(mainThread.getName()+"即將進入休眠");

        try {

            Thread.sleep(5000);

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

       

        // 中斷線程

        t.interrupt();

       

        System.out.println(mainThread.getName()+"休眠完成");

    }

 

  1. [5] yield()

public static void main(String[] args) {

 

         Thread mainThread = Thread.currentThread();

 

         Thread04 t = new Thread04("線程A");

         t.start();

 

        

         for (int i = 0; i < 5; i++) {

              if (i == 2) {

                   // yield 使當前禮讓一次

                   Thread.yield();

              }

              System.out.println(mainThread.getName() + "->" + i);

         }

     }

 

A hint to the scheduler that the current thread is willing to yield its current use of a processor. The scheduler is free to ignore this hint.

 

當前線程給cpu調度器一個暗示,暗示其想禮讓一次其擁有的cpu,CPU調度者也能夠狐狸此次暗示。此時當前線程進入就緒狀態。

 

[6] 線程的終止。

目前而言,不推薦使用stop直接終止線程。用interrupt()方法去中斷正在執行的線程,而在線程內部必定要寫捕獲中斷的異常。經過異常處理機制正常結束線程。

 

  1. 線程的安全問題(線程同步)

線程在執行過程當中,經過cpu的調度,執行軌跡不肯定,對共享資源的訪問很容易形成數據的錯誤。咱們稱這個錯亂稱爲線程安全問題。

 

  1. 同步概念

原子性操做:一個操做要麼一次性作完,要麼根本不開始,不存在中間狀態。

案例:ATM取現操做

 

同步就是讓操做保持原子性!java提供兩種方式實現同步。

  1. 同步代碼塊

把全部的同步操做放到同步代碼塊中,

synchronized (mutex) {

   // .. .

}

 

mutex 稱爲互斥鎖/同步鎖。對共享資源進行加鎖實現同步。通常用共享資源做爲同步鎖,也稱同步監視器。

public class MyRun implements Runnable {

    

     // 共享資源

     private int count = 5;

 

     @Override

     public void run() {

         // 模擬一個窗口5我的

         for (int i = 0; i < 5; i++) {

              // 同步代碼塊

              // mutex 互斥鎖

              synchronized (this) {

                   if (count > 0) {

                      

                       try {

                            Thread.sleep(3000);

                            count--;

                       } catch (InterruptedException e) {

                            e.printStackTrace();

                       }

                      

                       System.out.println(Thread.currentThread().getName()+"賣出一張票,還剩" + count + "張票");

                   }

              }

         }

     }

}

 

總結

synchronized(obj){}中的obj稱爲同步監視器

同步代碼塊中同步監視器能夠是任何對象,可是推薦使用共享資源做爲同步監視器

 

  1. 同步方法

若是同步代碼(原子性)不少,能夠考慮使用同步方法。

把普通方法用 synchronized 修飾,同步方法的同步監視器是this。

public class MyRun implements Runnable {

   

    // 共享資源

    private int count = 5;

 

    @Override

    public void run() {

        // 模擬一個窗口5我的

        for (int i = 0; i < 5; i++) {

           

            this.saleTicket();

           

        }

    }

   

    // 同步方法默認對this加鎖

    private synchronized void saleTicket() {

        if (count > 0) {

           

            try {

                Thread.sleep(3000);

                count--;

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

           

            System.out.println(Thread.currentThread().getName()+"賣出一張票,還剩" + count + "張票");

        }

    }

 

  1. 死鎖(C)

線程t1,擁有A資源,再次申請B資源,線程t2,擁有B資源,再申請A資源,t1由於沒有申請到B資源而進入阻塞;t2由於沒有申請到A資源進入阻塞。此時兩個線程都處於阻塞狀態而不能正常結束,而此時cpu空轉,這種狀況稱爲死鎖。

相關文章
相關標籤/搜索