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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

Java多线程(review)

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

文章目錄

  • 線程狀態(tài)
  • 線程方法
  • 線程停止
  • 線程休眠——sleep
    • 網(wǎng)絡(luò)延時(shí)
    • 模擬倒計(jì)時(shí)與打印當(dāng)前系統(tǒng)時(shí)間
  • 線程禮讓——yield
  • 線程強(qiáng)制執(zhí)行——Join
  • 線程狀態(tài)
  • 線程優(yōu)先級
  • 守護(hù)線程
  • 不安全案例
  • 死鎖
  • Lock鎖

線程狀態(tài)

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

線程方法

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

上述方法是被 Thread 對象調(diào)用的,下面表格的方法是 Thread 類的靜態(tài)方法。

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

線程停止

  • 建議線程正常停止–>利用次數(shù),不建議死循環(huán)
  • 建議使用標(biāo)志位–>設(shè)置一個(gè)標(biāo)志位
    設(shè)置一個(gè)公開的方法停止線程,轉(zhuǎn)換標(biāo)志位
  • 不要使用stop或者destory等過時(shí)或者JDK不建議使用的方法
  • package com.zeng.state; //測試停止線程 //1.建議線程正常停止-->利用次數(shù),不建議死循環(huán) //2。 建議使用標(biāo)志位-->設(shè)置一個(gè)標(biāo)志位 //3. 不要使用stop或者destory等過時(shí)或者JDK不建議使用的方法 public class TestStop implements Runnable{//設(shè)置一個(gè)標(biāo)志位private boolean flag=true;@Overridepublic void run() {int i=0;while(flag){//當(dāng)線程flag=false,則終止線程運(yùn)行System.out.println("run....Thread"+i++);}}//設(shè)置一個(gè)公開的方法停止線程,轉(zhuǎn)換標(biāo)志位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(時(shí)間)指定當(dāng)前線程阻塞的毫秒數(shù);
    • sleep存在異常InterruptedException;
    • sleep時(shí)間達(dá)到后線程進(jìn)入就緒狀態(tài)
    • sleep可以模擬網(wǎng)絡(luò)延時(shí),倒計(jì)時(shí)等。
    • 每個(gè)對象都有一個(gè)鎖,sleep不會釋放鎖。

    網(wǎng)絡(luò)延時(shí)

    • 模擬網(wǎng)絡(luò)延時(shí):擴(kuò)大線程的發(fā)生性
    package com.zeng.state;import com.zeng.demo01.TestThread03; //模擬網(wǎng)絡(luò)延時(shí):擴(kuò)大線程的發(fā)生性 public class TestSleep implements Runnable{//票數(shù)private int ticketNums=10;@Overridepublic void run() {while(true){if(ticketNums<=0){break;}// 模擬延時(shí)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();} }

    模擬倒計(jì)時(shí)與打印當(dāng)前系統(tǒng)時(shí)間

    package com.zeng.state;import java.text.SimpleDateFormat; import java.util.Date;//模擬倒計(jì)時(shí) public class TestSleep02 {public static void main(String[] args) throws InterruptedException {//模擬倒計(jì)時(shí)(調(diào)用靜態(tài)方法)// tenDown();//打印當(dāng)前系統(tǒng)時(shí)間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());//獲取當(dāng)前時(shí)間} catch (InterruptedException e) {e.printStackTrace();}}}public static /*加上static可以直接調(diào)用(靜態(tài)方法)*/void tenDown() throws InterruptedException {int num=10;while(true){Thread.sleep(1000);//sleep存在異常,拋出System.out.println(num--);if(num<=0){break;}}} }

    線程禮讓——yield

    • 禮讓線程,讓正在執(zhí)行的線程暫停,但不阻塞
    • 將線程狀態(tài)轉(zhuǎn)為就緒狀態(tài)
    • 讓CPU重新調(diào)度,禮讓不一定成功!
    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()+"線程開始執(zhí)行");Thread.yield();//線程禮讓System.out.println(Thread.currentThread().getName()+"線程停止執(zhí)行");} }

    線程強(qiáng)制執(zhí)行——Join

    • Join合并線程,待此線程執(zhí)行完成后,再執(zhí)行其他線程,其他線程阻塞
    • 可以想象成插隊(duì)
    package com.zeng.state; //測試join方法 想象為插隊(duì) 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();//插隊(duì)}System.out.println("main"+i);}} }

    線程狀態(tài)

    線程狀態(tài)。 線程可以處于以下狀態(tài)之一:

    狀態(tài)說明
    NEW尚未啟動的線程處于此狀態(tài)。
    RUNNABLE在Java虛擬機(jī)中執(zhí)行的線程處于此狀態(tài)。
    BLOCKED被阻塞等待監(jiān)視器鎖定的線程處于此狀態(tài)。
    WAITING正在等待另一個(gè)線程執(zhí)行特定動作的線程處于此狀態(tài)。
    TIMED_WAITING正在等待另一個(gè)線程執(zhí)行動作達(dá)到指定等待時(shí)間的線程處于此狀態(tài)。
    TERMINATED已退出的線程處于此狀態(tài)。

    一個(gè)線程可以在給定時(shí)間點(diǎn)處于一個(gè)狀態(tài)。 這些狀態(tài)是不反映任何操作系統(tǒng)線程狀態(tài)的虛擬機(jī)狀態(tài)。

    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("///");});//觀察狀態(tài)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();線程進(jìn)入死亡狀態(tài)后,就不能再啟動,直接報(bào)錯(cuò)} }

    線程優(yōu)先級

    • java提供一個(gè)線程調(diào)度器來監(jiān)控程序中啟動后進(jìn)入就緒狀態(tài)的所有線程,線程調(diào)度器按照優(yōu)先級決定應(yīng)該調(diào)度哪個(gè)線程來執(zhí)行。
    • 線程的優(yōu)先級用數(shù)字表示,范圍從1~10;
      • Thread.MIN_PRIORITY=1;
      • Thread.MAX_PRIORITY=10;
      • Thread.NORM_PRIORITY=5;
    • 使用以下方式改變或獲取優(yōu)先級
      • getPriority().setPriority(int XXX)
      • 優(yōu)先級的設(shè)定建議在start()調(diào)度前(先設(shè)置優(yōu)先級,再啟動)
    • 優(yōu)先級低只意味著獲得調(diào)度的概率低,并不是優(yōu)先級低就不會被調(diào)用了,這都是看CPU調(diào)度
    package com.zeng.state; //測試線程的優(yōu)先級 public class TestPriority {public static void main(String[] args) {//主線程默認(rèn)優(yōu)先級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);//先設(shè)置優(yōu)先級,再啟動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());} }

    守護(hù)線程

    • 線程分為用戶線程和守護(hù)線程
    • 虛擬機(jī)必須保護(hù)用戶線程執(zhí)行完畢
    • 虛擬機(jī)不必等待守護(hù)線程執(zhí)行完畢
    • 如,后臺記錄日志操作,監(jiān)控內(nèi)存,垃圾回收等待
    package com.zeng.state; //測試守護(hù)線程 //人生只有三萬天 上帝守護(hù)你 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);//默認(rèn)false是用戶線程,正常的線程都是用戶線程。。。thread.start();//上帝守護(hù)線程啟動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; //不安全的買票 //線程不安全,有負(fù)數(shù)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;}//模擬延時(shí)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());} }

    死鎖

    • 產(chǎn)生死鎖的四個(gè)必要條件
      • 互斥條件:一個(gè)資源每次只能被一個(gè)進(jìn)程使用。
      • 請求與保持條件:一個(gè)進(jìn)程因請求資源而阻塞時(shí),對已獲得的資源保持不放。
      • 不剝奪條件:進(jìn)程已獲得的資源,在未使用完之前,不能強(qiáng)行剝奪。
      • 循環(huán)等待條件:若干進(jìn)程之間形成一種頭尾相接的循環(huán)等待資源關(guān)系。
    package com.zeng.thread; //死鎖:多個(gè)線程互相抱著對方的資源,然后形成僵持。 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是顯式鎖(手動開啟和關(guān)閉鎖,別忘記關(guān)閉鎖)synchronized是隱式鎖,出了作用域自動釋放。
    • Lock只有代碼塊鎖,synchronized有代碼塊鎖和方法鎖
    • 使用Lock鎖,JVM花費(fèi)較少的時(shí)間來調(diào)度線程,性能更好。并且具有更好的擴(kuò)展性(提供更多的子類)
    • 優(yōu)先使用順序
      • Lock>同步代碼塊(已經(jīng)進(jìn)入方法體,分配了相應(yīng)資源)>同步方法(在方法體之外)
    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語句塊}}} }

    總結(jié)

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

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。