1. 程式人生 > >Java線程和進程

Java線程和進程

click ide 成員 color 設備 執行 rgs orm lock

一.線程

  1.什麽是線程:

    線程是進程的一個實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位。一個進程至少包含一個線程,也可以多個,線程屬於進程。

  2.Java中線程經歷的四個過程:

    (1)創建:

      創建一個Java線程常見的有兩種方式:繼承Thread類和實現Runnable接口這兩種方式。

    (2)執行:

線程創建後僅僅占有了內存資源,在JVM管理的線程中還沒有該線程,該線程必須調用start方法通知JVM,這樣JVM就會知道又有一個新的線程排隊等候了。如果當前線程輪到了CPU的使用權限的話,當前線程就會繼續執行。

(3)中斷:

  a.JVM將CPU的使用權限從當前線程切換到其它線程,使本線程讓出CPU的使用權限而處於中斷狀態。

   b.線程在執行過程中調用了sleep方法,使當前線程處於休眠狀態。

   c.線程在執行的過程中調用wait方法

   d.線程在使用cpu資源期間,執行了某個操作而進如阻塞狀態。

 (4)死亡

  死亡的線程不在具有執行能力。線程死亡的原因有二:

     a.線程正常運行結束而引起的死亡,即run方法執行完畢。

    b.線程被提前強制終止。

  3.Thread類:

    3.1構造方法:

構造方法摘要
Thread()
分配新的 Thread 對象。
Thread(Runnable target)
分配新的 Thread 對象。
Thread
(Runnable target, String name)

分配新的 Thread 對象。
Thread(String name)
分配新的 Thread 對象。
Thread(ThreadGroup group, Runnable target)
分配新的 Thread 對象。
Thread(ThreadGroup group, Runnable target, String name)
分配新的 Thread 對象,以便將 target 作為其運行對象,將指定的 name 作為其名稱,並作為 group 所引用的線程組的一員。
Thread(ThreadGroup group, Runnable target, String name, long stackSize)
分配新的 Thread 對象,以便將 target 作為其運行對象,將指定的 name 作為其名稱,作為 group 所引用的線程組的一員,並具有指定的堆棧大小
Thread(ThreadGroup group, String name)
分配新的 Thread 對象。

    3.2常用方法:  

方法摘要
long getId()
返回該線程的標識符。
String getName()
返回該線程的名稱。
int getPriority()
返回線程的優先級。
void interrupt()
中斷線程。
static boolean interrupted()
測試當前線程是否已經中斷。
boolean isAlive()
測試線程是否處於活動狀態。
boolean isDaemon()
測試該線程是否為守護線程。
void join()
等待該線程終止。
void join(long millis)
等待該線程終止的時間最長為 millis 毫秒。
void join(long millis, int nanos)
等待該線程終止的時間最長為 millis 毫秒 + nanos 納秒。
void run()
如果該線程是使用獨立的 Runnable 運行對象構造的,則調用該 Runnable 對象的 run 方法;否則,該方法不執行任何操作並返回。
void setName(String name)
改變線程名稱,使之與參數 name 相同。
void setPriority(int newPriority)
更改線程的優先級。
static void sleep(long millis)
在指定的毫秒數內讓當前正在執行的線程休眠(暫停執行),此操作受到系統計時器和調度程序精度和準確性的影響。
static void sleep(long millis, int nanos)
在指定的毫秒數加指定的納秒數內讓當前正在執行的線程休眠(暫停執行),此操作受到系統計時器和調度程序精度和準確性的影響。
void start()
使該線程開始執行;Java 虛擬機調用該線程的 run 方法。

    3.3相關方法使用:

      (1)繼承實現Thread類:

技術分享圖片
 1 package com.swpu.thread;
 2 class MyThread extends Thread{
 3     public MyThread(String name){
 4         super(name);
 5     }
 6     public void run(){
 7         for(int i=0;i<10;i++){
 8             System.out.println(getName()+"正在運行"+(i+1));
 9         }
10         
11     }
12 }
13 public class ThreadTest {
14 
15     public static void main(String[] args) {
16         // TODO Auto-generated method stub
17         MyThread mythread1=new MyThread("線程1");
18         MyThread mythread2=new MyThread("線程2");
19         mythread1.start();
20         mythread2.start();
21 
22 
23 
24     }
25 
26 }
View Code

      (2)實現Runnable接口:

          為什麽要實現Runnable接口:Java不支持多繼承了不打算重寫Thread類的其他方法。

技術分享圖片
 1 package com.swpu.thread;
 2 
 3 class PrintRunnable implements Runnable {
 4     @Override
 5     public void run() {
 6         // TODO Auto-generated method stub
 7         for (int i = 1; i < 10; i++) {
 8             System.out.println(Thread.currentThread().getName() + "正在運行"+(i++));
 9         }
10     }
11 }
12 
13 public class ThreadTest {
14 
15     public static void main(String[] args) {
16         // TODO Auto-generated method stub
17         //如果都是使用的pr1,那就相當於資源共享
18         PrintRunnable pr1 = new PrintRunnable();
19         Thread th1 = new Thread(pr1);
20         PrintRunnable pr2 = new PrintRunnable();
21         Thread th2 = new Thread(pr2);
22         th1.start();
23         th2.start();
24 
25     }
26 
27 }
View Code

    3.4線程的狀態:

技術分享圖片

    3.5正在運行狀態---->阻塞狀態相關方法使用:

      (1)sleep():

        在指定的毫秒數內讓正在執行的線程休眠(暫停執行),參數是休眠的時間(毫秒)。

        使用場景:定期刷新某項東西,計時間等

技術分享圖片
 1 package com.swpu.thread;
 2 
 3 class PrintRunnable implements Runnable {
 4     @Override
 5     public void run() {
 6         // TODO Auto-generated method stub
 7         for (int i = 1; i < 10;) {
 8             System.out.println(Thread.currentThread().getName() + "正在運行" + (i++));
 9             //需要捕獲異常(運行時退出)
10             try {
11                 //休眠時間結束後,線程不會立即變成執行狀態,而是變成可執行狀態,需要獲取CPU使用權才能變成執行狀態
12                 //因此時間需要多花一點
13                 Thread.sleep(1000);
14             } catch (InterruptedException e) {
15                 e.printStackTrace();    
16             }
17         }
18     }
19 }
20 
21 public class ThreadTest {
22 
23     public static void main(String[] args) {
24         // TODO Auto-generated method stub
25         // 如果都是使用的pr1,那就相當於資源共享
26         PrintRunnable pr1 = new PrintRunnable();
27         Thread th1 = new Thread(pr1);
28         PrintRunnable pr2 = new PrintRunnable();
29         Thread th2 = new Thread(pr2);
30         th1.start();
31         th2.start();
32 
33     }
34 
35 }
View Code
     (2)join():

        等待該方法的線程結束後才能執行。也有個參數為毫秒,等待線程終止的最長時間為多少毫秒(即在該線程執行的最長時間,無論線程是否結束都會執行其他線程)。 

技術分享圖片
 1 package com.swpu;
 2 
 3 class MyThread extends Thread {
 4     public void run() {
 5         for (int i = 0; i < 10; i++) {
 6             System.out.println(getName() + "執行第" + (i + 1));
 7         }
 8     }
 9 
10 }
11 
12 public class ThreadTest {
13 
14     public static void main(String[] args) {
15         // TODO Auto-generated method stub
16         MyThread mythread = new MyThread();
17         mythread.start();
18         try{
19         //搶占資源,會等待Thread-0運行完成後,其他線程才能執行
20         mythread.join();
21         }
22         catch(InterruptedException e){
23             e.printStackTrace();
24         }
25         for(int i=0;i<10;i++){
26             System.out.println("主線程運行第"+(i+1));
27         }
28         
29 
30     }
31 
32 }
View Code

    3.6線程優先級:(優先級的設置與操作系統及工作環境都有關)

      Java線程類提供10個優先級;

      優先級可以用整個整數1-10表示,超過範圍會拋出異常;

      主線程默認優先級為5。

      優先級常量:MAX_PRIORITY:線程的最高優先級10,MIN_PRIORITY:線程的最低優先級1,NORM_PRIORITY:線程的默認優先級5(主線程為5)

      優先級方法:getPriority()獲得優先級,setPriority()設置優先級、

技術分享圖片
 1 package com.swpu;
 2 
 3 class MyThread extends Thread {
 4     public void run() {
 5         for(int i=0;i<50;i++){
 6         System.out.println(getName()+"運行完成"+(i+1));
 7         }
 8     }
 9 
10 }
11 
12 public class ThreadTest {
13 
14     public static void main(String[] args) {
15         // TODO Auto-generated method stub
16         int mainPriority=Thread.currentThread().getPriority();
17         System.out.println("主線程優先級為:"+mainPriority);
18         MyThread mythread1 = new MyThread();
19         MyThread mythread2 = new MyThread();
20         //設置兩個線程的優先級
21         mythread1.setPriority(Thread.MAX_PRIORITY);
22         mythread2.setPriority(Thread.MIN_PRIORITY);
23         mythread1.start();
24         mythread2.start();
25 
26     
27 
28     }
29 
30 }
View Code

  4.線程中的問題及線程同步:

    各個線程是通過競爭CPU時間而獲得運行時間的;

    各CPU什麽時候得到CPU時間,占用多久,是不可預測的;

    一個正在運行的線程在什麽地方被暫停是不確定的。

    線程同步:synchronized關鍵字用在成員方法,靜態方法,語句塊。【防止執行過程中語句未執行完整跳到另一個線程,使取得的數據有誤差】

  5.線程間通信:

    wait():在其他線程調用此對象的 notify() 方法或 notifyAll() 方法前,導致當前線程等待;
  notify(): 喚醒在此對象監視器上等待的單個線程;

    notifyAll(): 喚醒在此對象監視器上等待的所有線程。

    例:

      Queue:

技術分享圖片
 1 package com.swpu.queue;
 2 
 3 public class Queue {
 4     private int n;
 5     boolean flag=false;
 6     public synchronized int get() {
 7         if(!flag){
 8             try{
 9                 wait();
10             }
11             catch(InterruptedException e){
12                 e.printStackTrace();
13             }
14         }
15         System.out.println("獲取:"+n);
16         flag=false;//消費完畢
17         //喚醒所有線程,notify()隨機喚醒一個
18         notifyAll();
19         return n;
20     }
21 
22     public synchronized void set(int n) {
23         if(flag){
24             try{
25                 wait();
26             }
27             catch(InterruptedException e){
28                 e.printStackTrace();
29             }
30         }
31         System.out.println("設置:"+n);
32         this.n = n;
33         flag=true;//容器中已經有數據
34         notifyAll();
35     }
36     
37 
38 }
View Code

      Producer:

技術分享圖片
 1 package com.swpu.queue;
 2 
 3 public class Producer implements Runnable{
 4     Queue queue;
 5     Producer(Queue queue){
 6         this.queue=queue;
 7     }
 8     @Override
 9     public void run() {
10         int i=0;
11         while(true){
12             queue.set(i++);
13             try {
14                 Thread.sleep(1000);
15             } catch (InterruptedException e) {
16                 e.printStackTrace();
17             } 
18         }
19     }
20 }
View Code

      Consumer:

技術分享圖片
 1 package com.swpu.queue;
 2 
 3 public class Consumer implements Runnable {
 4     Queue queue;
 5 
 6     Consumer(Queue queue) {
 7         this.queue = queue;
 8     }
 9 
10     @Override
11     public void run() {
12 
13         while (true) {
14             queue.get();
15             try {
16                 Thread.sleep(1000);
17             } catch (InterruptedException e) {
18                 e.printStackTrace();
19             }
20         }
21     }
22 
23 }
View Code

      Test:

技術分享圖片
 1 package com.swpu.queue;
 2 
 3 public class Test {
 4     public static void main(String[] args){
 5         Queue queue=new Queue();
 6         new Thread(new Producer(queue)).start();
 7         new Thread(new Consumer(queue)).start();
 8     } 
 9 
10 }
View Code

  6.Java各種線程鎖:

    https://www.jianshu.com/p/fa084227c96b

二.進程

  1.什麽是進程:  

    進程是程序的一次動態執行,它對應著從代碼加載,執行至執行完畢的一個完整的過程,是一個動態的實體,它有自己的生命周期。它因創建而產生,因調度而運行,因等待資源或事件而被處於等待狀態,因完成任務而被撤消。反映了一個程序在一定的數據 集上運行的全部動態過程。通過進程控制塊(PCB)唯一的標識某個進程。同時進程占據著相應的資源(例如包括cpu的使用 ,輪轉時間以及一些其它設備的權限)。是系統進行資源分配和調度的一個獨立單位。

  2.程序:

    一段靜態的代碼,一組指令的有序集合,它本身沒有任何運行的含義,它只是一個靜態的實體,是應用軟件執行的藍本。

  3.進程和程序的區別:

進程和程序的區別
狀態 是否具有資源 是否有唯一標識 是否具有並發性
進程   動態   √   √   √
程序   靜態   ×   √   ×

  4.進程的狀態及轉換:

    (1)就緒(Ready)狀態

     當進程已分配到除CPU以外的所有必要資源後,只要在獲得CPU,便可立即執行,進程這時的狀態就稱為就緒狀態。在一個系統中處於就緒狀態的進程可能有多個,通常將他們排成一個隊列,稱為就緒隊列。

   (2)執行狀態

     進程已獲得CPU,其程序正在執行。在單處理機系統中,只有一個進程處於執行狀態;再多處理機系統中,則有多個進程處於執行狀態。

   (3)阻塞狀態

     正在執行的進程由於發生某事件而暫時無法繼續執行時,便放棄處理機而處於暫停狀態,亦即程序的執行受到阻塞,把這種暫停狀態稱為阻塞狀態,有時也稱為等待狀態或封鎖狀態。

技術分享圖片

  5.多進程相關實現:

    https://blog.csdn.net/cq340321/article/details/53364512/

三.相關參考

  程序,線程,進程詳解:https://www.cnblogs.com/xiohao/p/4310644.html

Java線程和進程