中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當前位置: 首頁 > news >正文

小游戲大全網(wǎng)站論壇企業(yè)推廣

小游戲大全網(wǎng)站,論壇企業(yè)推廣,wordpress主題個人博客,動態(tài)網(wǎng)站開發(fā)考試答案目錄 Thread構(gòu)造方法Thread 的常見屬性創(chuàng)建一個線程獲取當前線程引用終止一個線程使用標志位使用自帶的標志位 等待一個線程線程休眠線程狀態(tài)線程安全線程不安全原因總結(jié)解決由先前線程不安全問題例子 Thread構(gòu)造方法 方法說明Thread()創(chuàng)建線程對象Thread(Runnable target)使用…

目錄

  • Thread構(gòu)造方法
  • Thread 的常見屬性
  • 創(chuàng)建一個線程
  • 獲取當前線程引用
  • 終止一個線程
    • 使用標志位
    • 使用自帶的標志位
  • 等待一個線程
  • 線程休眠
  • 線程狀態(tài)
  • 線程安全
    • 線程不安全原因總結(jié)
    • 解決由先前線程不安全問題例子

Thread構(gòu)造方法

方法說明
Thread()創(chuàng)建線程對象
Thread(Runnable target)使用 Runnable 對象創(chuàng)建線程對象
Thread(String name)創(chuàng)建線程對象,并命名(當前線程名)
Thread(Runnable target, String name)使用 Runnable 對象創(chuàng)建線程對象,并命名
Thread(ThreadGroup group,Runnable target)線程可以被用來分組管理,分好的組即為線程組

Thread 的常見屬性

屬性獲取方法
IDgetId()
名稱getName()
狀態(tài)getState()
優(yōu)先級getPriority()
是否后臺線程isDaemon()
是否存活isAlive()
是否被中斷isInterrupted()

解釋:

  • ID 是線程的唯一標識,不同線程不會重復,但是這里的id是Java給的id,不是前面PCB中說的id。
  • 名稱在各種調(diào)試工具用到,前面構(gòu)造方法給的名稱就是這個。
  • 狀態(tài)表示線程當前所處的一個情況。
  • 優(yōu)先級高的線程理論上來說更容易被調(diào)度到,但是這個是系統(tǒng)微觀程度上的,很難感知到。
  • 關于后臺線程,需要記住一點:JVM會在一個進程的所有非后臺線程(前臺線程)結(jié)束后,才會結(jié)束運行,而后臺線程不影響Java進程的結(jié)束,可以在start()調(diào)用前使用setDaemon(true)來設置線程為后臺線程。
  • 是否存活,即簡單的理解,為 run 方法是否運行結(jié)束了

創(chuàng)建一個線程

在前一篇文章中就介紹了相關操作,在這簡單提一下一定要使用線程變量名.start();創(chuàng)建一個新線程,start()方法是Java提供的API來調(diào)用系統(tǒng)中創(chuàng)建線程的方法。而run()方法是這個線程要干的事情,在線程創(chuàng)建好之后自動就會調(diào)用。
每個線程對象只能start一次。

獲取當前線程引用

方法說明
public static Thread currentThread();返回當前線程對象的引用

是靜態(tài)方法直接使用Thread.currentThread();就可以獲取到當前的線程引用。

終止一個線程

在Java中終止一個線程的思路就是讓線程中的run()方法盡快結(jié)束。

使用標志位

由于線程遲遲不結(jié)束大多是因為里面有循環(huán)語句,我們就可以使用一個成員變量來控制循環(huán)的結(jié)束。
不能使用局部變量定義在main方法內(nèi),因為雖然lambda表達式可以捕獲上層變量,但是這個變量不可以進行修改。

public class Demo {private static boolean isQuit = false;public static void main(String[] args) {Thread thread = new Thread(() ->{while(isQuit) {//具體操作  }});thread.start();isQuit = true;}
}

使用自帶的標志位

方法說明
public void interrupt()中斷對象關聯(lián)的線程,如果線程正在阻塞,則以異常方式通知,否則設置標志位
public static boolean interrupted()判斷當前線程的中斷標志位是否設置,調(diào)用后清除標志位,不建議使用,靜態(tài)方法為所有線程共用的
public boolean isInterrupted()判斷對象關聯(lián)的線程的標志位是否設置,調(diào)用后不清除標志位

Java中自帶了標志位來標志是否結(jié)束循環(huán)。先使用Thread.currentThread()獲取到當前線程,在.isInterrupted()獲取標志位。然后再主進程中調(diào)用interrupte()方法來將標志位值修改為true。

public class Demo {public static void main(String[] args) {Thread thread = new Thread(() ->{while (!Thread.currentThread().isInterrupted()) {//操作}});thread.start();thread.interrupt();}
}

但是如果在線程中有捕獲InterruptedException異常的語句,那么會在調(diào)用interrupte()同時捕獲到該異常,并且消除標志位。
此時我們就可以在catch語句中自己選擇是將線程結(jié)束還是進行其它操作。

public class Demo {public static void main(String[] args) {Thread thread = new Thread(() ->{while (!Thread.currentThread().isInterrupted()) {try {Thread.sleep(1000);} catch (InterruptedException e) {//1.不操作繼續(xù)執(zhí)行線程e.printStackTrace();//2.結(jié)束線程break;//3.進行其它操作}}});thread.start();thread.interrupt();}
}

等待一個線程

方法說明
public void join()等待線程結(jié)束
public void join(long millis)等待線程結(jié)束,最多等 millis 毫秒
public void join(long millis, int nanos)等待線程結(jié)束,最多等 millis 毫秒,但可以更高精度

在主線程中調(diào)用線程對象.join();就是等待線程對象執(zhí)行完再執(zhí)行主線程。
調(diào)用細節(jié):

  • 調(diào)用線程對象.join();就會讓該線程執(zhí)行完才繼續(xù)執(zhí)行外面的線程,如果線程對象對應的線程一直不結(jié)束那么外面的線程就會一直等(死等)
  • 調(diào)用線程對象.join(long millis);就會在該線程執(zhí)行millis毫秒后執(zhí)行外面的線程。
  • 如果遇到調(diào)用join前線程已經(jīng)結(jié)束,外面的線程不會陷入等待。

如下代碼執(zhí)行結(jié)果就是先打印5個thread線程,最后在打印main線程:

public class Demo6 {public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(() -> {for(int i = 0; i < 5; i++) {System.out.println("thread線程");}});       thread。start();thread.join();System.out.println("main線程");}
}

線程休眠

方法說明
public static void sleep(long millis) throws InterruptedException休眠當前線程 millis毫秒
public static void sleep(long millis, int nanos) throws InterruptedException可以更高精度的休眠

在系統(tǒng)讓線程休眠sleep中的參數(shù)毫秒后,線程會被喚醒從阻塞狀態(tài)變成就緒狀態(tài),但不會馬上執(zhí)行,涉及到調(diào)度開銷。所以實際使用的時間是大于sleep中的參數(shù)的。
并且在Windows和Linux系統(tǒng)上達到毫秒級誤差。

線程狀態(tài)

在操作系統(tǒng)里面進程和線程最重要的狀態(tài)就是:就緒狀態(tài)和阻塞狀態(tài)。
在Java中又給線程又給線程賦予了一些其他狀態(tài)。
線程的狀態(tài)是一個枚舉類型 Thread.State。

狀態(tài)說明
newThread對象已經(jīng)創(chuàng)建,但是start方法沒有調(diào)用
terminatedThread對象還在,但是內(nèi)核中線程已將結(jié)束了
Runnable就緒狀態(tài),線程已經(jīng)在CPU上執(zhí)行或者在CPU上等待執(zhí)行
timed_waiting由于sleep這種固定時間產(chǎn)生的阻塞
waiting由于wait這種不固定時間產(chǎn)生的阻塞
blocked由于鎖競爭產(chǎn)生的阻塞

線程安全

線程安全的簡單說法就是符不符合預期:如果多線程環(huán)境下代碼運行的結(jié)果是符合我們預期的,即在單線程環(huán)境應該的結(jié)果,則說這個程序是線程安全的。

例如以下代碼:
我們的預期結(jié)果是10000,但是其實每次的結(jié)果都是不一樣的,這種就是線程不安全。

public class Demo {private static int ret;public static void main(String[] args) throws InterruptedException {Thread thread1 = new Thread(() -> {for (int i = 0; i < 5000; i++) {ret++;}});Thread thread2 = new Thread(() -> {for (int i = 0; i < 5000; i++) {ret++;}});thread1.start();thread2.start();thread1.join();thread2.join();System.out.println(ret);;}
}

就以上訴代碼例子來講解出現(xiàn)線程不安全的原因。

在CPU上實現(xiàn)自增操作主要有三步:

  1. 將數(shù)據(jù)給到CPU的寄存器中;
  2. 數(shù)據(jù)在寄存器中加1;
  3. 將數(shù)據(jù)返回到內(nèi)存中。

就以一個thread1和一個thread2來說,每個線程都進行這三步操作,但是線程在CPU上又是隨機調(diào)用的,這就相當于有六個位置隨機坐,相當于排列組合的A66,當數(shù)據(jù)作為不同線程的開始值進入寄存器時就相當于兩次自增只執(zhí)行了一次。

但是線程調(diào)用就更加復雜了,線程數(shù)量不一樣,順序不一樣,這就相當于有無數(shù)種可能了,所以結(jié)果是不可控的,就導致了線程不安全的情況。

線程不安全原因總結(jié)

在介紹線程不安全原因之前先介紹一個概念:原子性。

原子性:簡單來講就是執(zhí)行一段代碼連續(xù)執(zhí)行完不被其他線程干擾。舉個例子:

我們把一段代碼想象成一個房間,每個線程就是要進入這個房間的人。如果沒有任何機制保證,A進入房間之后,還沒有出來;B 是不是也可以進入房間,打斷 A 在房間里的隱私。這個就是不具備原子性的。

那我們應該如何解決這個問題呢?是不是只要給房間加一把鎖,A 進去就把門鎖上,其他人是不是就進不來了。這樣就保證了這段代碼的原子性了。

有時也把這個現(xiàn)象叫做同步互斥,表示操作是互相排斥的。

原因總結(jié):

  • 操作系統(tǒng)調(diào)度線程是隨機的(搶占式執(zhí)行);
  • 多個線程對同一個變量進行修改;
  • 修改操作不是原子性的;
  • 內(nèi)存可見性問題;
  • 指令重排序問題。

解決由先前線程不安全問題例子

要解決就要從原因入手:

  • 操作系統(tǒng)隨機調(diào)度是操作系統(tǒng)帶來的解決不了;
  • 多個線程對一個變量修改,有些可以規(guī)避,但有些根據(jù)需求無法規(guī)避。
  • 將操作改為原子性,可以通過synchronized關鍵字 加鎖操作來實現(xiàn)。

語法:

synchronized(變量){
//修改操作
}

()括號內(nèi)的變量不重要,作用是區(qū)分加鎖對象是否一樣,如果對同一個對象加鎖,那么兩個操作就會產(chǎn)生“blocked”鎖競爭阻塞問題,后一個線程就會等到前一個線程解鎖再執(zhí)行。
進入左大括號 ‘{’ 就是加鎖,出了右大括號 ‘}’ 就是解鎖。

對上訴代碼進行如下修改,就會出現(xiàn)預期結(jié)果10000:

public class Demo7 {private static int ret;public static void main(String[] args) throws InterruptedException {Object block = new Object();Thread thread1 = new Thread(() -> {for (int i = 0; i < 5000; i++) {synchronized (block){ret++;}}});Thread thread2 = new Thread(() -> {for (int i = 0; i < 5000; i++) {synchronized (block){ret++;}}});thread1.start();thread2.start();thread1.join();thread2.join();System.out.println(ret);;}
}

synchronized還可以修飾方法(靜態(tài)方法也行)。

  • synchronized修飾實例方法:
class Counter{public int ret;public void increase1() {synchronized (this) {ret++;}}//簡化版本synchronized public void increase2() {ret++;}
}
  • synchronized修飾靜態(tài)方法:相當于修飾這個類
class Counter{private static int ret2;public static void increase3() {synchronized (Counter.class) {ret2++;}}//簡化版本synchronized public static void increase4() {ret2++;}
}
http://www.risenshineclean.com/news/37902.html

相關文章:

  • wordpress程序圖片打開慢成都比較靠譜的seo
  • 企業(yè)網(wǎng)站搭建流程國內(nèi)新聞摘抄
  • 深圳小程序開發(fā)費用南京百度搜索優(yōu)化
  • 免費永久網(wǎng)站建設網(wǎng)絡營銷的8個基本職能
  • 網(wǎng)站建設需要用到哪些軟件周口網(wǎng)絡推廣哪家好
  • 安徽展覽展示公司排名無線網(wǎng)絡優(yōu)化
  • 設計網(wǎng)站如何推廣方案百度怎么做關鍵詞優(yōu)化
  • 黃頁模式優(yōu)化人員配置
  • 直播系統(tǒng)平臺搭建佛山網(wǎng)站設計實力樂云seo
  • 杭州螞蟻 做網(wǎng)站的公司鄭州今日頭條
  • 家具公司網(wǎng)頁設計搜索引擎優(yōu)化的策略主要有
  • centos7裝wordpressseo站內(nèi)優(yōu)化和站外優(yōu)化
  • 0元試用網(wǎng)站開發(fā)廈門網(wǎng)站建設公司哪家好
  • 找網(wǎng)站開發(fā)公司成品視頻直播軟件推薦哪個好用
  • 做圍棋題最好的網(wǎng)站域名解析ip138在線查詢
  • 長春市做網(wǎng)站推廣成人速成班有哪些專業(yè)
  • 網(wǎng)站首頁如何做浮動窗口自學seo大概需要多久
  • 大慶公司做網(wǎng)站效果好的關鍵詞如何優(yōu)化
  • 廈門哪里做網(wǎng)站網(wǎng)上競價平臺
  • 網(wǎng)站一級目錄seo自然搜索優(yōu)化排名
  • dw做網(wǎng)站背景圖片設置鋪平網(wǎng)頁怎么搜索關鍵詞
  • 惠州有做網(wǎng)站的嗎免費個人自助建站
  • 南昌專業(yè)做網(wǎng)站公司有哪些電腦優(yōu)化工具
  • 黃驊烈士網(wǎng)奇seo培訓官網(wǎng)
  • 建設網(wǎng)站預算廣州seo營銷培訓
  • 17網(wǎng)店貨源網(wǎng)seo綜合查詢系統(tǒng)
  • 深圳定制網(wǎng)站公司免費seo關鍵詞優(yōu)化排名
  • 江門網(wǎng)站推廣軟件關鍵詞排名提高
  • 網(wǎng)頁設計配色時可以用關鍵詞是網(wǎng)站seo的核心工作
  • 云臺山旅游景區(qū)網(wǎng)站建設內(nèi)容業(yè)務推廣方式有哪些