多线程1
1-1 進程
程序是靜止的,運行中的程序就是進程。
- 進程的三個特征:
- 動態(tài)性 : 進程是運行中的程序,要動態(tài)的占用內(nèi)存,CPU和網(wǎng)絡(luò)等資源。
- 獨立性 : 進程與進程之間是相關(guān)獨立的,彼此有自己的獨立內(nèi)存區(qū)域。
- 并發(fā)性 : 假如CPU是單核,同一個時刻其實內(nèi)存中只有一個進程在被執(zhí)行。 CPU會分時輪詢切換依次為每個進程服務(wù),因為切換的速度非快,給我們的感覺這些進程在==同時執(zhí)行,這就是并發(fā)性。==
- 并行:同一個時刻同時在執(zhí)行。
1-2 線程
- 線程是屬于進程的。==一個進程可以包含多個線程,這就是多線程==。線程創(chuàng)建開銷相對于進程來說比較小。 線程也支持并發(fā)性。
- 線程的作用: 可以提高程序的效率,可以有更多機會得到CPU。
1-3 進程和線程的總結(jié)
進程是運行中的程序。有動態(tài)性,獨立性,并發(fā)性。一個進程可以包含多個線程,線程也支持并發(fā)。
多線程可以提高程序的整體效率,可以解決很多業(yè)務(wù)需求。因為多個線程是并發(fā)搶占CPU執(zhí)行,所以多線程的執(zhí)行會出現(xiàn)隨機性。
2-創(chuàng)建線程的三種方式
方式1:定義一個線程類繼承Thread類,然后重寫run()方法,再創(chuàng)建線程對象,調(diào)用start()方法啟動線程
/** 方式一的步驟:a.定義一個線程類繼承Thread類b.重寫Thread類的run()方法c.創(chuàng)建一個子線程對象d.調(diào)用線程對象的start()方法啟動線程(其實最終就是執(zhí)行線程對象的run()方法)線程的注意:1.啟動線程不能直接調(diào)用run()方法,否則是普通對象的普通方法調(diào)用了,將失去線程特征。線程的啟動必須調(diào)用start()2.一般是先創(chuàng)建子線程,再申明主線程的任務(wù),否則主線程任務(wù)總是先執(zhí)行完!優(yōu)缺點:優(yōu)點:編碼簡單。缺點:線程類已經(jīng)繼承了Thread類,不能再繼承其他類,功能被削弱了。不能做線程池。無法直接返回線程執(zhí)行的結(jié)果。*/ public class ThreadDemo {// 自帶一個線程:main方法本身就是一個線程,是最牛逼的線程!public static void main(String[] args) {// c.創(chuàng)建一個子線程對象MyThread t = new MyThread();// d.啟動線程// 注意:啟動線程不能直接調(diào)用run()方法,否則是普通對象的普通方法調(diào)用了,將失去線程特征。// 線程的啟動必須調(diào)用start()t.start();for(int i = 0 ; i < 10; i++){System.out.println("main線程執(zhí)行:"+i);}} }// 線程類不是線程對象,是用來創(chuàng)建線程對象的。 // a.定義一個線程類繼承Thread類 class MyThread extends Thread{// b.重寫Thread類的run()方法@Overridepublic void run() {for(int i = 0 ; i < 10; i++){System.out.println("子線程執(zhí)行:"+i);}} }方式2:定義一個線程任務(wù)類實現(xiàn)Runnable接口,然后重寫run()方法。創(chuàng)建線程任務(wù)對象,把線程任務(wù)對象包裝成線程對象,調(diào)用start()方法啟動線程
/** a.定義一個線程任務(wù)類實現(xiàn)Runnable接口。重寫run()方法 b.創(chuàng)建一個線程任務(wù)對象 c.把線程任務(wù)對象包裝成一個線程對象-- public Thread(Runnable target) d.調(diào)用線程對象的start()方法啟動線程。優(yōu)缺點:缺點:編程相對復(fù)雜,不能直接返回線程的執(zhí)行結(jié)果優(yōu)點:1. 一個任務(wù)對象可以被反復(fù)包裝成多個線程對象。2. 可以避免java中的單繼承的局限性。因為線程任務(wù)對象只是實現(xiàn)了接口,還可以繼續(xù)繼承其他類和實現(xiàn)其他接口。3. 實現(xiàn)解耦操作,線程任務(wù)對象代碼可以被多個線程共享,代碼和線程獨立。4. 線程池只能放入實現(xiàn)Runable或Callable類線程,不能直接放入繼承Thread的類。適合做線程池。*/ public class ThreadDemo {public static void main(String[] args) {// b.創(chuàng)建一個線程任務(wù)對象Runnable target = new MyRunnable();// c.把線程任務(wù)對象包裝成線程對象Thread t = new Thread(target);// d.調(diào)用線程對象的start()方法啟動線程。t.start();Thread t1 = new Thread(target);t1.start();for(int i = 0 ; i < 10; i++){System.out.println(Thread.currentThread().getName()+"=>"+i);}}} // 線程任務(wù)類 // a.定義一個線程任務(wù)類實現(xiàn)Runnable接口。 class MyRunnable implements Runnable{@Overridepublic void run() {for(int i = 0 ; i < 10; i++){System.out.println(Thread.currentThread().getName()+"=>"+i);}} }方式三:定義一個線程任務(wù)類實現(xiàn)Callable接口
/** a.定義一個線程任務(wù)類實現(xiàn)Callable接口。 b.重寫call()方法。 c.把線程任務(wù)對象包裝成一個未來任務(wù)對象。 d.把未來任務(wù)對象包裝成一個線程對象。 e.調(diào)用線程對象的start()方法啟動線程。 優(yōu)缺點:缺點:編碼復(fù)雜。優(yōu)點:全是優(yōu)點。可以繼續(xù)繼承其他類??梢宰鼍€程池。可以得到線程返回的結(jié)果??梢宰鲑Y源共享操作*/ public class ThreadDemo {public static void main(String[] args) {MyCallable call = new MyCallable();// c.把線程任務(wù)對象包裝成一個未來任務(wù)對象。/*** 未來任務(wù)對象: FutureTask* 1.可以通過未來任務(wù)對象去獲取線程執(zhí)行的結(jié)果。* 2.未來任務(wù)對象其實就是一個Runnable的對象。*/FutureTask<String> target = new FutureTask<>(call);// d.把未來任務(wù)對象包裝成一個線程對象。Thread t = new Thread(target);// e.調(diào)用線程對象的start()方法啟動線程。t.start();for(int i = 0 ; i < 10; i++){System.out.println(Thread.currentThread().getName()+"=>"+i);}try {// 線程的執(zhí)行的結(jié)果!String result = target.get();System.out.println(result);} catch (Exception e) {e.printStackTrace();}} } // a.定義一個線程任務(wù)類實現(xiàn)Callable接口。申明返回值類型 class MyCallable implements Callable<String>{// b.重寫call()方法。@Overridepublic String call() throws Exception {int count = 0 ;for(int i = 0 ; i < 10; i++){count+=(i+1) ; // 1-10的和。System.out.println(Thread.currentThread().getName()+"=>"+i);}return Thread.currentThread().getName()+"求和結(jié)果:"+count;} }轉(zhuǎn)載于:https://www.cnblogs.com/Guard9/p/11152841.html
總結(jié)
- 上一篇: 梦到被男人骂什么预兆
- 下一篇: 矩阵的理解经典博客