Java線程和進程
一.線程
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 分配新的 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線程和進程