這篇文章主要介紹“Java線程核心機制是什么”,在日常操作中,相信很多人在Java線程核心機制是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Java線程核心機制是什么”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!
成都創(chuàng)新互聯(lián)堅持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:成都網(wǎng)站建設(shè)、網(wǎng)站制作、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時代的汪清網(wǎng)站設(shè)計、移動媒體設(shè)計的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!
并發(fā)編程的特點是:可以將程序劃分為多個分離且獨立運行的任務(wù),通過線程來驅(qū)動這些獨立的任務(wù)執(zhí)行,從而提升整體的效率。下面提供一個基礎(chǔ)的演示案例。
場景:假設(shè)有一個容器集合,需要拿出容器中的每個元素,進行加工處理,一般情況下直接遍歷就好,如果數(shù)據(jù)偏大,可以根據(jù)線程數(shù)量對集合切割,每個線程處理一部分?jǐn)?shù)據(jù),這樣處理時間就會減少很多。
public class ExtendThread01 { public static void main(String[] args) { List
注意:這里案例只是對場景原理的實現(xiàn),在開發(fā)中,是不允許這種操作的,需要使用線程池處理,后續(xù)會說。如果集合沒有控制好,導(dǎo)致大量創(chuàng)建Thread線程,導(dǎo)致內(nèi)存溢出。
線程啟動后執(zhí)行任務(wù)方法,在執(zhí)行過程中可以被阻塞,休眠,喚醒,停止等一系列狀態(tài)操作。
線程休眠作用:當(dāng)線程一部分任務(wù)執(zhí)行完畢后進入休眠(阻塞)狀態(tài),線程調(diào)度器可以切換到另外線程,這對分布任務(wù)的執(zhí)行相對公平。
public class ExtendThread02 { public static void main(String[] args) { StopThread stopThread = new StopThread() ; stopThread.start(); // 標(biāo)記當(dāng)前線程停止信號,且拋出中斷異常,但沒有停止 stopThread.interrupt(); // 判斷當(dāng)前線程是否已經(jīng)是終止?fàn)顟B(tài) System.out.println("1=="+stopThread.isInterrupted()); // 清除當(dāng)前線程的終止信號 System.out.println("2=="+stopThread.interrupted()); // 再次判斷當(dāng)前線程狀態(tài) System.out.println("3=="+stopThread.isInterrupted()); System.out.println("main end ..."); } } class StopThread extends Thread { @Override public void run() { for (int i = 0 ; i < 10 ; i++){ try { System.out.println(Thread.currentThread().getId()+"="+i); // 線程阻塞1秒 Thread.sleep(1000); } catch (InterruptedException e){ e.printStackTrace(); } } } }
sleep(long millis)
:線程休眠指定的時間,進入阻塞狀態(tài);
interrupt()
:切換線程為中斷狀態(tài),拋出中斷異常,不會停止線程,可以監(jiān)視線程的中斷狀態(tài)并定義執(zhí)行策略。
interrupted()
:清除調(diào)用該方法線程的中斷狀態(tài),也不會影響線程的執(zhí)行,且返回當(dāng)前執(zhí)行‘stopThread.interrupted()’的線程是否中斷,這里就是指main線程是否中斷。
isInterrupted()
:判斷調(diào)用該方法的線程是否已經(jīng)是中斷狀態(tài)。
補刀一句
:線程的這幾個方法極其容易混淆,需要斷點源碼追蹤一下看看,進入源碼方法,調(diào)用相關(guān)API查看一下狀態(tài)。(附斷點圖一張:)
CPU執(zhí)行和處理線程的順序是不確定的,但是線程調(diào)度器傾向執(zhí)行線程優(yōu)先級高的線程,線程優(yōu)先級高說明獲取CPU資源的概率高,或者獲取的執(zhí)行時間分片多,但不代表優(yōu)先級低的一定最后執(zhí)行。
public class ExtendThread03 { public static void main(String[] args) { Priority01 priority01 = new Priority01(); priority01.start(); System.out.println("priority01="+priority01.getPriority()); Priority02 priority02 = new Priority02(); priority02.start(); System.out.println("priority02="+priority02.getPriority()); priority01.setPriority(10); priority02.setPriority(1); } } class Priority01 extends Thread { @Override public void run() { for (int i = 0 ; i < 100 ; i++){ System.out.println(Thread.currentThread().getName()+";i="+i); } } } class Priority02 extends Thread { @Override public void run() { for (int a = 0 ; a < 100 ; a++){ System.out.println(Thread.currentThread().getName()+";a="+a); } } }
注意
:優(yōu)先級范圍[MAX_PRIORITY=10,MIN_PRIORITY=1],如果超出范圍會拋出IllegalArgumentException異常。
建議
:通常實際開發(fā)中,是不允許輕易修改線程運行的參數(shù),容易引發(fā)認(rèn)知之外的異常。
如果在線程A中,執(zhí)行線程B的加入方法,那么A線程就會等待線程B執(zhí)行完畢再返回繼續(xù)執(zhí)行。
public class ExtendThread04 { public static void main(String[] args) { JoinThreadA joinThreadA = new JoinThreadA() ; joinThreadA.start(); } } class JoinThreadA extends Thread { @Override public void run() { System.out.println("缺水中..."); JoinThreadB joinThreadB = new JoinThreadB() ; joinThreadB.start(); try{ joinThreadB.join(); } catch (Exception e){ e.printStackTrace(); } System.out.println("喝水中..."); } } class JoinThreadB extends Thread { @Override public void run() { System.out.println("買水中..."); try{ TimeUnit.SECONDS.sleep(2); } catch (Exception e){ e.printStackTrace(); } System.out.println("買到水..."); } }
注意
:可以設(shè)置線程的加入時間join(long),畢竟等不到雪月風(fēng)花,人生都是有時差,只能后會無期了。
本地的線程變量,底層維護ThreadLocalMap存儲值:
static class Entry extends WeakReference> { Object value; Entry(ThreadLocal> k, Object v) { super(k); value = v; } }
即以Key-Value鍵值對的方式存儲數(shù)據(jù)。如果對集合容器的源碼熟悉的話,這個Entry就是似曾相識感覺。
public class ExtendThread05 { private static final ThreadLocalthreadLocal = new ThreadLocal<>() ; private static void initBegin (){ threadLocal.set(System.currentTimeMillis()); } private static Long overTime (){ return System.currentTimeMillis()-threadLocal.get(); } public static void main(String[] args) throws Exception { ExtendThread05.initBegin(); TimeUnit.SECONDS.sleep(3); System.out.println(ExtendThread05.overTime()); } }
ThreadLocal提供線程內(nèi)存儲變量的能力,并且綁定到當(dāng)前線程,通過get和set方法就可以得到和設(shè)置當(dāng)前線程對應(yīng)的值。這個在web開發(fā)中是常見的應(yīng)用。
守護線程是支持輔助型線程,主要在程序中起到調(diào)度和支持性作用,當(dāng)Jvm中非守護線程全部結(jié)束,守護線程也就會結(jié)束。
public class ExtendThread06 { public static void main(String[] args) throws Exception { InputStreamReader is = new InputStreamReader(System.in); BufferedReader br = new BufferedReader(is); String value = br.readLine(); CheckThread checkThread = new CheckThread(value) ; checkThread.setDaemon(true); checkThread.start(); System.out.println("Main End ..."); } } class CheckThread extends Thread { private String spell ; public CheckThread (String spell){ this.spell = spell ; } @Override public void run() { if (spell.startsWith("cs")){ System.out.println(spell+":輸入正確"); } else { System.out.println(spell+":輸入錯誤"); } try { TimeUnit.SECONDS.sleep(10); } catch (InterruptedException e){ e.printStackTrace(); } } }
注意
:守護線程需要顯式調(diào)用setDaemon(true);方法,這里可以看到main線程結(jié)束,整合程序就結(jié)束了,絲毫理會休眠中的守護線程。如果打斷非守護線程的休眠,試試會不會拋你一臉異常?
按照J(rèn)ava中異常處理機制,拋異常逐級降低,線程的任務(wù)方法run沒有拋異常,那重寫或者實現(xiàn)的方法自然不能直接throws異常出去。多線程中推薦捕獲異常,可以針對性處理機制。
public class ExtendThread07 { public static void main(String[] args) { TryThread tryThread = new TryThread(); tryThread.setName("try-name"); // 定義運行中異常處理策略 MyExe myExe = new MyExe() ; tryThread.setUncaughtExceptionHandler(myExe); tryThread.start(); } } class TryThread extends Thread { @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e){ e.printStackTrace(); } // 如何處理這里異常? Integer.parseInt("cicada") ; } } class MyExe implements Thread.UncaughtExceptionHandler { @Override public void uncaughtException(Thread t, Throwable e) { System.out.println(t.getName()+";異常:"+e.getMessage()); } }
通過實現(xiàn)UncaughtExceptionHandler接口,并且線程要指定自定義異常處理對象,也可以處理未檢查的異常。
到此,關(guān)于“Java線程核心機制是什么”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>
分享文章:Java線程核心機制是什么
標(biāo)題來源:http://weahome.cn/article/pgcdih.html