1.實現(xiàn)多線程
1.1簡單了解多線程
是指從軟件或者硬件上實現(xiàn)多個線程并發(fā)執(zhí)行的技術(shù)。
具有多線程能力的計算機因有硬件支持而能夠在同一時間執(zhí)行多個線程,提升性能。
1.2并發(fā)和并行
-
并行:在同一時刻,有多個指令在多個CPU上同時執(zhí)行。
-
并發(fā):在同一時刻,有多個指令在單個CPU上交替執(zhí)行。
1.3進程和線程
-
進程:是正在運行的程序
獨立性:進程是一個能獨立運行的基本單位,同時也是系統(tǒng)分配資源和調(diào)度的獨立單位
動態(tài)性:進程的實質(zhì)是程序的一次執(zhí)行過程,進程是動態(tài)產(chǎn)生,動態(tài)消亡的
并發(fā)性:任何進程都可以同其他進程一起并發(fā)執(zhí)行 -
線程:是進程中的單個順序控制流,是一條執(zhí)行路徑
? 單線程:一個進程如果只有一條執(zhí)行路徑,則稱為單線程程序
? 多線程:一個進程如果有多條執(zhí)行路徑,則稱為多線程程序
1.4實現(xiàn)多線程方式一:繼承Thread類【應(yīng)用】
-
方法介紹
方法名 說明 void run() 在線程開啟后,此方法將被調(diào)用執(zhí)行 void start() 使此線程開始執(zhí)行,Java虛擬機會調(diào)用run方法() -
實現(xiàn)步驟
- 定義一個類MyThread繼承Thread類
- 在MyThread類中重寫run()方法
- 創(chuàng)建MyThread類的對象
- 啟動線程
-
代碼演示文章來源:http://www.zghlxwxcb.cn/news/detail-716662.html
public class MyThread extends Thread { @Override public void run() { for(int i=0; i<100; i++) { System.out.println(i); } } } public class MyThreadDemo { public static void main(String[] args) { MyThread my1 = new MyThread(); MyThread my2 = new MyThread(); // my1.run(); // my2.run(); //void start() 導(dǎo)致此線程開始執(zhí)行; Java虛擬機調(diào)用此線程的run方法 my1.start(); my2.start(); } }
-
兩個小問題
-
為什么要重寫run()方法?
因為run()是用來封裝被線程執(zhí)行的代碼
-
run()方法和start()方法的區(qū)別?
run():封裝線程執(zhí)行的代碼,直接調(diào)用,相當(dāng)于普通方法的調(diào)用
start():啟動線程;然后由JVM調(diào)用此線程的run()方法
-
1.5實現(xiàn)多線程方式二:實現(xiàn)Runnable接口【應(yīng)用】
-
Thread構(gòu)造方法
方法名 說明 Thread(Runnable target) 分配一個新的Thread對象 Thread(Runnable target, String name) 分配一個新的Thread對象 -
實現(xiàn)步驟
- 定義一個類MyRunnable實現(xiàn)Runnable接口
- 在MyRunnable類中重寫run()方法
- 創(chuàng)建MyRunnable類的對象
- 創(chuàng)建Thread類的對象,把MyRunnable對象作為構(gòu)造方法的參數(shù)
- 啟動線程
-
代碼演示
public class MyRunnable implements Runnable { @Override public void run() { for(int i=0; i<100; i++) { System.out.println(Thread.currentThread().getName()+":"+i); } } } public class MyRunnableDemo { public static void main(String[] args) { //創(chuàng)建MyRunnable類的對象 MyRunnable my = new MyRunnable(); //創(chuàng)建Thread類的對象,把MyRunnable對象作為構(gòu)造方法的參數(shù) //Thread(Runnable target) // Thread t1 = new Thread(my); // Thread t2 = new Thread(my); //Thread(Runnable target, String name) Thread t1 = new Thread(my,"坦克"); Thread t2 = new Thread(my,"飛機"); //啟動線程 t1.start(); t2.start(); } }
1.6實現(xiàn)多線程方式三: 實現(xiàn)Callable接口【應(yīng)用】
-
方法介紹
方法名 說明 V call() 計算結(jié)果,如果無法計算結(jié)果,則拋出一個異常 FutureTask(Callable callable) 創(chuàng)建一個 FutureTask,一旦運行就執(zhí)行給定的 Callable V get() 如有必要,等待計算完成,然后獲取其結(jié)果 -
實現(xiàn)步驟
- 定義一個類MyCallable實現(xiàn)Callable接口
- 在MyCallable類中重寫call()方法
- 創(chuàng)建MyCallable類的對象
- 創(chuàng)建Future的實現(xiàn)類FutureTask對象,把MyCallable對象作為構(gòu)造方法的參數(shù)
- 創(chuàng)建Thread類的對象,把FutureTask對象作為構(gòu)造方法的參數(shù)
- 啟動線程
- 再調(diào)用get方法,就可以獲取線程結(jié)束之后的結(jié)果。
-
代碼演示
public class MyCallable implements Callable<String> { @Override public String call() throws Exception { for (int i = 0; i < 100; i++) { System.out.println("跟女孩表白" + i); } //返回值就表示線程運行完畢之后的結(jié)果 return "答應(yīng)"; } } public class Demo { public static void main(String[] args) throws ExecutionException, InterruptedException { //線程開啟之后需要執(zhí)行里面的call方法 MyCallable mc = new MyCallable(); //Thread t1 = new Thread(mc); //可以獲取線程執(zhí)行完畢之后的結(jié)果.也可以作為參數(shù)傳遞給Thread對象 FutureTask<String> ft = new FutureTask<>(mc); //創(chuàng)建線程對象 Thread t1 = new Thread(ft); String s = ft.get(); //開啟線程 t1.start(); //String s = ft.get(); System.out.println(s); } }
-
三種實現(xiàn)方式的對比
- 實現(xiàn)Runnable、Callable接口
- 好處: 擴展性強,實現(xiàn)該接口的同時還可以繼承其他的類
- 缺點: 編程相對復(fù)雜,不能直接使用Thread類中的方法
- 繼承Thread類
- 好處: 編程比較簡單,可以直接使用Thread類中的方法
- 缺點: 可以擴展性較差,不能再繼承其他的類
- 實現(xiàn)Runnable、Callable接口
1.7設(shè)置和獲取線程名稱【應(yīng)用】
-
方法介紹
方法名 說明 void setName(String name) 將此線程的名稱更改為等于參數(shù)name String getName() 返回此線程的名稱 Thread currentThread() 返回對當(dāng)前正在執(zhí)行的線程對象的引用 -
代碼演示
public class MyThread extends Thread { public MyThread() {} public MyThread(String name) { super(name); } @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println(getName()+":"+i); } } } public class MyThreadDemo { public static void main(String[] args) { MyThread my1 = new MyThread(); MyThread my2 = new MyThread(); //void setName(String name):將此線程的名稱更改為等于參數(shù) name my1.setName("高鐵"); my2.setName("飛機"); //Thread(String name) MyThread my1 = new MyThread("高鐵"); MyThread my2 = new MyThread("飛機"); my1.start(); my2.start(); //static Thread currentThread() 返回對當(dāng)前正在執(zhí)行的線程對象的引用 System.out.println(Thread.currentThread().getName()); } }
1.8線程休眠【應(yīng)用】
-
相關(guān)方法
方法名 說明 static void sleep(long millis) 使當(dāng)前正在執(zhí)行的線程停留(暫停執(zhí)行)指定的毫秒數(shù) -
代碼演示
public class MyRunnable implements Runnable { @Override public void run() { for (int i = 0; i < 100; i++) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "---" + i); } } } public class Demo { public static void main(String[] args) throws InterruptedException { /*System.out.println("睡覺前"); Thread.sleep(3000); System.out.println("睡醒了");*/ MyRunnable mr = new MyRunnable(); Thread t1 = new Thread(mr); Thread t2 = new Thread(mr); t1.start(); t2.start(); } }
1.9線程優(yōu)先級【應(yīng)用】
-
線程調(diào)度
-
兩種調(diào)度方式
- 分時調(diào)度模型:所有線程輪流使用 CPU 的使用權(quán),平均分配每個線程占用 CPU 的時間片
- 搶占式調(diào)度模型:優(yōu)先讓優(yōu)先級高的線程使用 CPU,如果線程的優(yōu)先級相同,那么會隨機選擇一個,優(yōu)先級高的線程獲取的 CPU 時間片相對多一些
-
Java使用的是搶占式調(diào)度模型
-
隨機性
假如計算機只有一個 CPU,那么 CPU 在某一個時刻只能執(zhí)行一條指令,線程只有得到CPU時間片,也就是使用權(quán),才可以執(zhí)行指令。所以說多線程程序的執(zhí)行是有隨機性,因為誰搶到CPU的使用權(quán)是不一定的
-
-
優(yōu)先級相關(guān)方法
方法名 說明 final int getPriority() 返回此線程的優(yōu)先級 final void setPriority(int newPriority) 更改此線程的優(yōu)先級線程默認(rèn)優(yōu)先級是5;線程優(yōu)先級的范圍是:1-10 -
代碼演示
public class MyCallable implements Callable<String> { @Override public String call() throws Exception { for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + "---" + i); } return "線程執(zhí)行完畢了"; } } public class Demo { public static void main(String[] args) { //優(yōu)先級: 1 - 10 默認(rèn)值:5 MyCallable mc = new MyCallable(); FutureTask<String> ft = new FutureTask<>(mc); Thread t1 = new Thread(ft); t1.setName("飛機"); t1.setPriority(10); //System.out.println(t1.getPriority());//5 t1.start(); MyCallable mc2 = new MyCallable(); FutureTask<String> ft2 = new FutureTask<>(mc2); Thread t2 = new Thread(ft2); t2.setName("坦克"); t2.setPriority(1); //System.out.println(t2.getPriority());//5 t2.start(); } }
1.10守護線程【應(yīng)用】
-
相關(guān)方法
方法名 說明 void setDaemon(boolean on) 將此線程標(biāo)記為守護線程,當(dāng)運行的線程都是守護線程時,Java虛擬機將退出 -
代碼演示
public class MyThread1 extends Thread { @Override public void run() { for (int i = 0; i < 10; i++) { System.out.println(getName() + "---" + i); } } } public class MyThread2 extends Thread { @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println(getName() + "---" + i); } } } public class Demo { public static void main(String[] args) { MyThread1 t1 = new MyThread1(); MyThread2 t2 = new MyThread2(); t1.setName("女神"); t2.setName("備胎"); //把第二個線程設(shè)置為守護線程 //當(dāng)普通線程執(zhí)行完之后,那么守護線程也沒有繼續(xù)運行下去的必要了. t2.setDaemon(true); t1.start(); t2.start(); } }
后記
????????美好的一天,到此結(jié)束,下次繼續(xù)努力!欲知后續(xù),請看下回分解,寫作不易,感謝大家的支持!! ??????文章來源地址http://www.zghlxwxcb.cn/news/detail-716662.html
到了這里,關(guān)于從零開始學(xué)習(xí) Java:簡單易懂的入門指南之多線程(三十四)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!