摘要:本人郵箱歡迎轉載轉載請注明網址代碼已經全部托管有需要的同學自行下載類學習線程的開發者首先遇到的第一個類就是通過使用類我們就可以啟動停止中斷一個線程在同一個時間片里可能會有多個線程在執行每個線程都擁有它自己的方法調用堆棧參數和變量每個至少會有
Thread類本人郵箱:
歡迎轉載,轉載請注明網址 http://blog.csdn.net/tianshi_kco
github: https://github.com/kco1989/kco
代碼已經全部托管github有需要的同學自行下載
學習java線程的開發者,首先遇到的第一個類就是Thread,通過使用Thread類,我們就可以啟動,停止,中斷一個線程. 在同一個時間片里, 可能會有多個線程在執行, 每個線程都擁有它自己的方法調用堆棧, 參數和變量.每個app至少會有一個線程--主線程(main thread).
創建一個線程 java創建線程有兩種方式創建一個繼承Thread的子類,并實現run方法
使用Thread的構造方法public Thread(Runnable target)創建,這個需要傳入一個實現Runnable接口的子類
實現下面我們分別以這兩種方式實現一下.
編寫SubThread繼承Thread,并覆蓋run方法 SubThread.java
public class SubThread extends Thread{ @Override public void run() { for (int i = 0; i < 10; i ++){ System.out.println(Thread.currentThread().getName() + ":" + i); } } public static void main(String[] args) { System.out.println("begin main"); SubThread sub = new SubThread(); sub.start(); System.out.println("end main"); } }
編寫SubRunnable實現Runnable,然后使用構造器Thread(Runnable) 創建一個線程
public class SubRunnable implements Runnable { @Override public void run() { for (int i = 0; i < 10; i ++){ System.out.println(Thread.currentThread().getName() + ":" + i); } } public static void main(String[] args) { System.out.println("begin main"); Thread thread = new Thread(new SubRunnable()); thread.start(); System.out.println("end main"); } }區別
使用第一種方法創建的話,你可以在run方法中,可以用this直接調用線程的方法,比如獲取線程的id-->this.getId()
而使用第二方法創建線程,在run中,this對象壓根就沒有getId()這個方法,這個時候你只能用Thread.cuurentThread()這個靜態方法獲取該線程.
在這里一般推薦使用第二種方法創建,因為這樣比較符合面對象的思路,Thread就只負責線程的啟動,停止,中斷等操作,而Runnable就只負責線程要運行某一個具體任務.
讓線程"睡"一會不管使用那種方式創建線程,都可以調用Thread.cuurentThread()獲取當前的線程
還有,Thread其實也是Runnable的一個子類
除了上面兩種創建方法,其中還有另外一種方法創建線程,那就是實現ThreadFactory接口,這種比較適合批量生成某一種規格的線程
調用線程的Thread.sleep()方法會讓線程睡眠一段時間,這個時候線程會掛起,然后將CPU的時間片轉移給其他線程,讓其他線程獲得執行的機會.
停止線程Thread.sleep()接收一個毫秒值做完參數,并拋出一個InterruptedException異常.
不管是使用哪一種方法創建線程,run方法的任務執行完了,線程就自動停止.
如果想在中途就停止線程,有下面幾種方式
調用線程的interrupt()方法,這時線程的中斷位會被標識,并拋出InterruptedException,例如:
public class StopThread1 { public static void main(String[] args) throws InterruptedException { System.out.println("begin main"); Thread thread = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 10; i ++){ try { Thread.sleep(100); System.out.println(Thread.currentThread().getName() + ":" + i); } catch (InterruptedException e) { break; } } } }); thread.start(); System.out.println("main sleep 500ms"); Thread.sleep(500); thread.interrupt(); System.out.println("end main"); } }
在調用thread.interrupt();這個語句時,會對該線程的中斷狀態標識為true,然后在拋出InterruptedException異常時,會清空該中斷位.
修改程序,在拋出InterruptedException中添加System.out.println("InterruptedException:" + Thread.currentThread().isInterrupted());,然后再thread.interrupt();后面添加System.out.println("thread.isInterrupted:" + thread.isInterrupted());.然后運行程序.這時候運行結果有可能打印出thread.isInterrupted:true;InterruptedException:false或者打印出thread.isInterrupted:false;InterruptedException:false,運行多次結果都有可能不一致,這個是因為主線程和子線程都通知在執行,還沒有來的及執行主線程的打印語句,子線程異常中的打印語句就已經執行了.
可以在線程中加一個boolean成員變量,提供setter方法,然后在run方法中判斷該變量是否為true,若為true則停止線程,否則繼續
public class StopThread2 { public static class StopRunnable implements Runnable{ private boolean isStop = false; public void setStop(){ this.isStop = true; } @Override public void run() { int count = 0; while (!isStop){ try { Thread.sleep(100); System.out.println(Thread.currentThread().getName() + ":" + count++); } catch (InterruptedException e) { e.printStackTrace(); } } } } public static void main(String[] args) throws InterruptedException { System.out.println("begin main"); StopRunnable stop = new StopRunnable(); Thread thread = new Thread(stop); thread.start(); Thread.sleep(200); stop.setStop(); System.out.println("end main"); } }線程的屬性
id: 通過Thread.getId()可以獲取線程的id,線程的id是一個自增長的long, 不能修改
name: 通過Thread.getName(), 用一個字符串來標識線程的名字,可以通過Thread.setName()或部分構造器修改線程的名字
priority: 線程的優先級,線程創建默認優先級為5, 最小為優先級為1, 最大為10.優先級大的線程有機會先執行.但具體那個線程先執行還是要看CPU的心情了.
state: 線程的狀態, 線程的狀態有以下幾種
Thread.State.NEW: _新建狀態_:這個是線程已經被創建但還沒有調用"start()"方法時的狀態
Thread.State.RUNNABLE: 運行狀態 當前線程已經在JVM中執行
Thread.State.BLOCKED: 阻塞狀態 表示當前線程在等待進入一個同步塊或同步方法,也可以等到一個同步快被提交. 常見的有IO阻塞等.
Thread.State.WAITING: 等待狀態 但線程調用Object.wait(),Thread.join(),LockSupport.park()就會進入等待狀態.當前線程在等待其他線程執行某一個特定操作.比如:當前線程執行Object.wait(),那么就需要其他線程執行Object.notify()或Object.notifyAll(),如果線程執行了Thread.join(),則需要等到指定的線程執行結束.
Thread.State.TIMED_WAITING: 有時間的等待 線程在等待某一個等待的時間.比如,線程執行了Thread.sleep,Object.wait(long),Thread.join(long)等
Thread.State.TERMINATED: 終結 線程已經執行完畢.
daemon: 這個用來標識線程為守護線程或非守護線程的,默認創建的線程都是非守護線程.應用程序所有的非守護線程執行完畢之后,則程序就停止運行.比如主線程都是非守護線程,所以主線程會等到主線程的所有語句執行完成,程序才會停止運行.JVM的資源回收則是一個守護線程.
public class TestDaemonThread { public static void main(String[] args) { System.out.println("start main"); Thread thread = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 10; i ++){ try { System.out.println(Thread.currentThread().getName() + ":" + i); Thread.sleep(10); } catch (Exception e) { e.printStackTrace(); } } } }); thread.start(); System.out.println("end main"); } }
Thread.join()該例子中,程序必須等到主線程和子線程同時執行完成才會停止,因為默認創建的線程都是非守護線程,如果在thread.start();前加入thread.setDaemon(true);, 那么程序不會等子線程執行完才結束程序的.
等到某線程執行完畢才開始執行,如果調用Thread.join(long)則表示等到某線程執行完畢或指定的超時時間結束后才開始執行
public class ThreadJoinTest { public static void main(String[] args) throws InterruptedException { Thread thread1 = new Thread(() -> { for (int i = 0;i < 10; i ++){ try { Thread.sleep(10); System.out.println(Thread.currentThread().getName() + ":" + i); } catch (InterruptedException e) { e.printStackTrace(); } } }, "thread1"); Thread thread2 = new Thread(() -> { try { thread1.join(); for (int i = 0;i < 10; i ++){ Thread.sleep(10); System.out.println(Thread.currentThread().getName() + ":" + i); } } catch (InterruptedException e) { e.printStackTrace(); } }, "thread2"); thread1.start(); thread2.start(); } }
Thread.yield上面的例子,thread2線程會等thread1執行完之后才開始執行
這個方法標識當前線程會按時線程調度者讓其他線程先執行.但CPU是否讓其他線程優先執行,還是要看CPU的心情了.
線程的異常如果線程發現一些運行時異常而沒有在run方法俘獲,會怎么辦?
程序會打印出一推錯誤堆棧,如果我們先把線程的錯誤按照某種可讀的方式打印到問題,但又不想在每個run方法中增加try{...}catch(Exception e){...}怎么辦?
我們查看Thread類的源碼發現,在Thread中有一個內部接口UncaughtExceptionHandler,這個正是我們所需要的.實現這個接口,并調用Thread.setUncaughtExceptionHandler,那么但線程出現時,則會回調uncaughtException方法
public class ThreadExceptionTest { public static void main(String[] args) throws InterruptedException { System.out.println("begin main"); Thread thread = new Thread(() -> { int i = 1 / 0; },"myThread"); thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { @Override public void uncaughtException(Thread t, Throwable e) { System.out.println(String.format("%s發生異常%s", t.getName(), e.getMessage())); } }); thread.start(); System.out.println("end main"); } }打賞
如果覺得我的文章寫的還過得去的話,有錢就捧個錢場,沒錢給我捧個人場(幫我點贊或推薦一下)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/67044.html
摘要:多線程同步工具箱之篇前言的多線程協調工具,,,都是在多線程代碼中使用比較多的工具類之一。毫不夸張的說,這幾個類,是等同于解決多線程問的包,實在有必要添加到程序員的工具箱里面。 Java多線程同步工具箱之CountDownLatch篇 前言 Java的多線程協調工具CountDownLatch,Semaphore,CyclicBarrier,ReadWriteLock都是在多線程代碼中使...
摘要:多線程技術是個很龐大的課題,編程思想這本書英文版,以下簡稱中也用了頁介紹的多線程體系。一個線程歸屬于唯一的進程,線程無法脫離進程而存在。五線程內數據線程的私有數據僅歸屬于一個線程,不在線程之間共享,例如,,。 多線程技術是個很龐大的課題,《Java編程思想》這本書(英文版,以下簡稱TIJ)中也用了136頁介紹Java的多線程體系。的確,Java語言發展到今天,多線程機制相比其他的語言從...
摘要:時間年月日星期六說明本文部分內容均來自慕課網。慕課網教學源碼無學習源碼第一章課前準備前言課程說明比較和這兩種線程創建的方式,需要知道和的基本創建方式。一旦主線程獲取到了用戶的輸入,這時候,阻塞就會解除掉,主線程繼續運行,直到結束。 時間:2017年07月08日星期六說明:本文部分內容均來自慕課網。@慕課網:http://www.imooc.com教學源碼:無學習源碼:https://g...
摘要:本人郵箱歡迎轉載轉載請注明網址代碼已經全部托管有需要的同學自行下載引言在之前的例子我們要創建多個線程處理一批任務的時候我是通過創建線程數組或者使用線程集合來管理的但是這樣做不太好因為這些線程沒有被重復利用所以這里要引入線程池今天我們就講線程 本人郵箱: 歡迎轉載,轉載請注明網址 http://blog.csdn.net/tianshi_kcogithub: https://github...
摘要:目錄源碼之下無秘密做最好的源碼分析教程源碼分析之番外篇的前生今世的前生今世之一簡介的前生今世之二小結的前生今世之三詳解的前生今世之四詳解源碼分析之零磨刀不誤砍柴工源碼分析環境搭建源碼分析之一揭開神秘的紅蓋頭源碼分析之一揭開神秘的紅蓋頭客戶端 目錄 源碼之下無秘密 ── 做最好的 Netty 源碼分析教程 Netty 源碼分析之 番外篇 Java NIO 的前生今世 Java NI...
閱讀 2538·2023-04-26 00:57
閱讀 911·2021-11-25 09:43
閱讀 2221·2021-11-11 16:55
閱讀 2207·2019-08-30 15:53
閱讀 3592·2019-08-30 15:52
閱讀 1459·2019-08-30 14:10
閱讀 3379·2019-08-30 13:22
閱讀 1209·2019-08-29 11:18