日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java多线程(review)

發布時間:2023/12/4 java 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java多线程(review) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 線程狀態
  • 線程方法
  • 線程停止
  • 線程休眠——sleep
    • 網絡延時
    • 模擬倒計時與打印當前系統時間
  • 線程禮讓——yield
  • 線程強制執行——Join
  • 線程狀態
  • 線程優先級
  • 守護線程
  • 不安全案例
  • 死鎖
  • Lock鎖

線程狀態

  • 新建狀態:
    使用 new 關鍵字和 Thread 類或其子類建立一個線程對象后,該線程對象就處于新建狀態。它保持這個狀態直到程序 start() 這個線程。
  • 就緒狀態:
    當線程對象調用了start()方法之后,該線程就進入就緒狀態。就緒狀態的線程處于就緒隊列中,要等待JVM里線程調度器的調度。
  • 運行狀態:
    如果就緒狀態的線程獲取 CPU 資源,就可以執行 run(),此時線程便處于運行狀態。處于運行狀態的線程最為復雜,它可以變為阻塞狀態、就緒狀態和死亡狀態。
  • 阻塞狀態:
    如果一個線程執行了sleep(睡眠)、suspend(掛起)等方法,失去所占用資源之后,該線程就從運行狀態進入阻塞狀態。在睡眠時間已到或獲得設備資源后可以重新進入就緒狀態。可以分為三種:
  • 等待阻塞:運行狀態中的線程執行 wait() 方法,使線程進入到等待阻塞狀態。
  • 同步阻塞:線程在獲取 synchronized 同步鎖失敗(因為同步鎖被其他線程占用)。
  • 其他阻塞:通過調用線程的 sleep() 或 join() 發出了 I/O 請求時,線程就會進入到阻塞狀態。當sleep() 狀態超時,join() 等待線程終止或超時,或者 I/O 處理完畢,線程重新轉入就緒狀態。
  • 死亡狀態:
    一個運行狀態的線程完成任務或者其他終止條件發生時,該線程就切換到終止狀態。

線程方法

方法說明
public void start()使該線程開始執行;Java 虛擬機調用該線程的 run 方法。
public void run()如果該線程是使用獨立的 Runnable 運行對象構造的,則調用該 Runnable 對象的 run 方法;否則,該方法不執行任何操作并返回。
public final void setName(String name)改變線程名稱,使之與參數 name 相同。
public final void setPriority(int priority)更改線程的優先級。
public final void setDaemon(boolean on)將該線程標記為守護線程或用戶線程。
public final void join(long millisec)等待該線程終止的時間最長為 millis 毫秒。
public void interrupt()中斷線程。
public final boolean isAlive()測試線程是否處于活動狀態。

上述方法是被 Thread 對象調用的,下面表格的方法是 Thread 類的靜態方法。

方法描述
public static void yield()暫停當前正在執行的線程對象,并執行其他線程。
public static void sleep(long millisec)在指定的毫秒數內讓當前正在執行的線程休眠(暫停執行),此操作受到系統計時器和調度程序精度和準確性的影響。
public static boolean holdsLock(Object x)當且僅當當前線程在指定的對象上保持監視器鎖時,才返回 true。
public static Thread currentThread()返回對當前正在執行的線程對象的引用。
public static void dumpStack()將當前線程的堆棧跟蹤打印至標準錯誤流。

線程停止

  • 建議線程正常停止–>利用次數,不建議死循環
  • 建議使用標志位–>設置一個標志位
    設置一個公開的方法停止線程,轉換標志位
  • 不要使用stop或者destory等過時或者JDK不建議使用的方法
  • package com.zeng.state; //測試停止線程 //1.建議線程正常停止-->利用次數,不建議死循環 //2。 建議使用標志位-->設置一個標志位 //3. 不要使用stop或者destory等過時或者JDK不建議使用的方法 public class TestStop implements Runnable{//設置一個標志位private boolean flag=true;@Overridepublic void run() {int i=0;while(flag){//當線程flag=false,則終止線程運行System.out.println("run....Thread"+i++);}}//設置一個公開的方法停止線程,轉換標志位public void stop() {this.flag = false;}public static void main(String[] args) {TestStop testStop = new TestStop();new Thread(testStop).start();for(int i=0;i<1000;i++){System.out.println("main"+i);if(i==900){testStop.stop();System.out.println("線程停止");}}} }

    線程休眠——sleep

    • sleep(時間)指定當前線程阻塞的毫秒數;
    • sleep存在異常InterruptedException;
    • sleep時間達到后線程進入就緒狀態
    • sleep可以模擬網絡延時,倒計時等。
    • 每個對象都有一個鎖,sleep不會釋放鎖。

    網絡延時

    • 模擬網絡延時:擴大線程的發生性
    package com.zeng.state;import com.zeng.demo01.TestThread03; //模擬網絡延時:擴大線程的發生性 public class TestSleep implements Runnable{//票數private int ticketNums=10;@Overridepublic void run() {while(true){if(ticketNums<=0){break;}// 模擬延時try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"-->拿到了第"+ticketNums--+"票");}}public static void main(String[] args) {TestThread03 ticket = new TestThread03();new Thread(ticket,"小明").start();new Thread(ticket,"老師").start();new Thread(ticket,"黃牛黨").start();} }

    模擬倒計時與打印當前系統時間

    package com.zeng.state;import java.text.SimpleDateFormat; import java.util.Date;//模擬倒計時 public class TestSleep02 {public static void main(String[] args) throws InterruptedException {//模擬倒計時(調用靜態方法)// tenDown();//打印當前系統時間Date startTime = new Date(System.currentTimeMillis());while(true){try {// Date startTime = new Date(System.currentTimeMillis());Thread.sleep(1000);System.out.println(new SimpleDateFormat("HH:mm:ss").format(startTime));startTime = new Date(System.currentTimeMillis());//獲取當前時間} catch (InterruptedException e) {e.printStackTrace();}}}public static /*加上static可以直接調用(靜態方法)*/void tenDown() throws InterruptedException {int num=10;while(true){Thread.sleep(1000);//sleep存在異常,拋出System.out.println(num--);if(num<=0){break;}}} }

    線程禮讓——yield

    • 禮讓線程,讓正在執行的線程暫停,但不阻塞
    • 將線程狀態轉為就緒狀態
    • 讓CPU重新調度,禮讓不一定成功!
    package com.zeng.state; //測試禮讓線程 //禮讓不一定成功,全看CPU心情 public class TextYield {public static void main(String[] args) {MyYield myYield = new MyYield();new Thread(myYield,"a").start();new Thread(myYield,"b").start();} } class MyYield implements Runnable{@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+"線程開始執行");Thread.yield();//線程禮讓System.out.println(Thread.currentThread().getName()+"線程停止執行");} }

    線程強制執行——Join

    • Join合并線程,待此線程執行完成后,再執行其他線程,其他線程阻塞
    • 可以想象成插隊
    package com.zeng.state; //測試join方法 想象為插隊 public class TestJoin implements Runnable{@Overridepublic void run() {for (int i = 0; i < 100; i++) {System.out.println("線程VIP來了"+i);}}public static void main(String[] args) throws InterruptedException {//啟動我們的線程TestJoin testJoin = new TestJoin();Thread thread = new Thread(testJoin);thread.start();//主線程for (int i = 0; i < 1000; i++) {if(i==200){thread.join();//插隊}System.out.println("main"+i);}} }

    線程狀態

    線程狀態。 線程可以處于以下狀態之一:

    狀態說明
    NEW尚未啟動的線程處于此狀態。
    RUNNABLE在Java虛擬機中執行的線程處于此狀態。
    BLOCKED被阻塞等待監視器鎖定的線程處于此狀態。
    WAITING正在等待另一個線程執行特定動作的線程處于此狀態。
    TIMED_WAITING正在等待另一個線程執行動作達到指定等待時間的線程處于此狀態。
    TERMINATED已退出的線程處于此狀態。

    一個線程可以在給定時間點處于一個狀態。 這些狀態是不反映任何操作系統線程狀態的虛擬機狀態。

    package com.zeng.state;public class TestState {public static void main(String[] args) {Thread thread=new Thread(()->{for (int i = 0; i < 5; i++) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("///");});//觀察狀態Thread.State state = thread.getState();System.out.println(state);//new//觀察啟動后thread.start();//啟動線程state=thread.getState();System.out.println(state);//Runwhile(state!=Thread.State.TERMINATED){try {Thread.sleep(1000);state=thread.getState();System.out.println(state);} catch (InterruptedException e) {e.printStackTrace();}}// thread.start();線程進入死亡狀態后,就不能再啟動,直接報錯} }

    線程優先級

    • java提供一個線程調度器來監控程序中啟動后進入就緒狀態的所有線程,線程調度器按照優先級決定應該調度哪個線程來執行。
    • 線程的優先級用數字表示,范圍從1~10;
      • Thread.MIN_PRIORITY=1;
      • Thread.MAX_PRIORITY=10;
      • Thread.NORM_PRIORITY=5;
    • 使用以下方式改變或獲取優先級
      • getPriority().setPriority(int XXX)
      • 優先級的設定建議在start()調度前(先設置優先級,再啟動)
    • 優先級低只意味著獲得調度的概率低,并不是優先級低就不會被調用了,這都是看CPU調度
    package com.zeng.state; //測試線程的優先級 public class TestPriority {public static void main(String[] args) {//主線程默認優先級System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());MyPriority myPriority = new MyPriority();Thread t1 = new Thread(myPriority);Thread t2 = new Thread(myPriority);Thread t3 = new Thread(myPriority);Thread t4 = new Thread(myPriority);Thread t5 = new Thread(myPriority);Thread t6 = new Thread(myPriority);//先設置優先級,再啟動t1.start();t2.setPriority(1);t2.start();t3.setPriority(4);t3.start();t4.setPriority(Thread.MAX_PRIORITY);//MAX_PRIORITY=10t4.start();t5.setPriority(5);t5.start();t6.setPriority(7);t6.start();} } class MyPriority implements Runnable{@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());} }

    守護線程

    • 線程分為用戶線程和守護線程
    • 虛擬機必須保護用戶線程執行完畢
    • 虛擬機不必等待守護線程執行完畢
    • 如,后臺記錄日志操作,監控內存,垃圾回收等待
    package com.zeng.state; //測試守護線程 //人生只有三萬天 上帝守護你 public class TestDaemon {public static void main(String[] args) {God god = new God();You you = new You();Thread thread = new Thread(god);thread.setDaemon(true);//默認false是用戶線程,正常的線程都是用戶線程。。。thread.start();//上帝守護線程啟動new Thread(you).start();} } class God implements Runnable{@Overridepublic void run() {while(true){System.out.println("上帝保佑著你");}} }class You implements Runnable{@Overridepublic void run() {for (int i = 0; i < 30000; i++) {System.out.println("你一生都在開心的活著");}System.out.println("-=====goodbye world");} }

    不安全案例

    package com.zeng.syn; //不安全的買票 //線程不安全,有負數public class TestUnsafeBuyTicket {public static void main(String[] args) {BuyTicket station = new BuyTicket();new Thread(station,"我emo了").start();new Thread(station,"你笑了").start();new Thread(station,"可惡的黃牛").start();} }class BuyTicket implements Runnable{//票private int ticketNums=10;boolean flag=true;//外部停止方式@Overridepublic void run() {//買票while(flag){try {buy();} catch (InterruptedException e) {e.printStackTrace();}}}//synchronized 同步方法,鎖的是thisprivate synchronized void buy() throws InterruptedException {//判斷是否有票if(ticketNums<=0){flag=false;return;}//模擬延時Thread.sleep(100);//買票System.out.println(Thread.currentThread().getName()+"拿到"+ticketNums--);} } package com.zeng.syn;import java.util.ArrayList;//線程不安全的集合 public class TestUnsafeList {public static void main(String[] args) {ArrayList<String> list = new ArrayList<>();for (int i = 0; i < 10000; i++) {new Thread(()->{synchronized (list){list.add(Thread.currentThread().getName());}}).start();}try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(list.size());} } package com.zeng.syn;import java.util.concurrent.CopyOnWriteArrayList; //測試JUC安全類型的集合 public class TestJUc {public static void main(String[] args) {CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();for (int i = 0; i < 1000; i++) {new Thread(()->{list.add(Thread.currentThread().getName());});}try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(list.size());} }

    死鎖

    • 產生死鎖的四個必要條件
      • 互斥條件:一個資源每次只能被一個進程使用。
      • 請求與保持條件:一個進程因請求資源而阻塞時,對已獲得的資源保持不放。
      • 不剝奪條件:進程已獲得的資源,在未使用完之前,不能強行剝奪。
      • 循環等待條件:若干進程之間形成一種頭尾相接的循環等待資源關系。
    package com.zeng.thread; //死鎖:多個線程互相抱著對方的資源,然后形成僵持。 public class DeadLock {public static void main(String[] args) {Makeup s1 = new Makeup(0, "灰姑娘");Makeup s2 = new Makeup(0, "白雪公主");s1.start();s2.start();} } //口紅 class Lipstick{}//鏡子 class Mirror{} class Makeup extends Thread{//需要的資源只有一份,用static來保證只有一份static Lipstick lipstick=new Lipstick();static Mirror mirror=new Mirror();int choice;//選擇String girlName;//使用化妝品的人Makeup(int choice,String girlName){this.choice=choice;this.girlName=girlName;}@Overridepublic void run() {//化妝try {makeup();} catch (InterruptedException e) {e.printStackTrace();}}//化妝,互相持有對方的鎖,就是需要拿到對方的資源private void makeup() throws InterruptedException {if(choice==0){synchronized (lipstick){//獲得口紅的鎖System.out.println(this.girlName+"獲得口紅的鎖");Thread.sleep(1000); // synchronized (mirror){//一秒鐘獲得鏡子 // System.out.println(this.girlName+"獲得鏡子的鎖"); // }}synchronized (mirror){//一秒鐘獲得鏡子System.out.println(this.girlName+"獲得鏡子的鎖");}}else{synchronized (mirror){//一秒鐘獲得鏡子System.out.println(this.girlName+"獲得鏡子的鎖");Thread.sleep(1000); // synchronized (lipstick){//獲得口紅的鎖 // System.out.println(this.girlName+"獲得口紅的鎖"); // }}synchronized (lipstick){//獲得口紅的鎖System.out.println(this.girlName+"獲得口紅的鎖");}}} }

    Lock鎖

    • Lock是顯式鎖(手動開啟和關閉鎖,別忘記關閉鎖)synchronized是隱式鎖,出了作用域自動釋放。
    • Lock只有代碼塊鎖,synchronized有代碼塊鎖和方法鎖
    • 使用Lock鎖,JVM花費較少的時間來調度線程,性能更好。并且具有更好的擴展性(提供更多的子類)
    • 優先使用順序
      • Lock>同步代碼塊(已經進入方法體,分配了相應資源)>同步方法(在方法體之外)
    package com.zeng.thread;import java.util.concurrent.locks.ReentrantLock;public class TestLock {public static void main(String[] args) {TestLock2 testLock2 = new TestLock2();new Thread(testLock2).start();new Thread(testLock2).start();new Thread(testLock2).start();} }class TestLock2 implements Runnable{int ticketNums=10;//定義Lock鎖private final ReentrantLock lock=new ReentrantLock();@Overridepublic void run() {while(true){try {lock.lock();if(ticketNums>0){try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(ticketNums--);}else{break;}} finally {//解鎖lock.unlock();//如果同步代碼有異常,要將unlock()寫入finally語句塊}}} }

    總結

    以上是生活随笔為你收集整理的Java多线程(review)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。