多线程java_Java多线程基础
在開始之前,先來搞清楚兩個(gè)概念:進(jìn)程和線程。
進(jìn)程:進(jìn)程是具有一定獨(dú)立功能的程序關(guān)于某個(gè)數(shù)據(jù)集合上的一次運(yùn)行活動(dòng),是系統(tǒng)進(jìn)行資源分配和調(diào)度的一個(gè)獨(dú)立單位。
線程:線程是進(jìn)程的一個(gè)實(shí)體,是CPU調(diào)度和分派的基本單位,它是比進(jìn)程更小的能獨(dú)立運(yùn)行的基本單位,線程自己基本上不擁有系統(tǒng)資源,只擁有一點(diǎn)在運(yùn)行中必不可少的資源(如程序計(jì)數(shù)器,一組寄存器和棧),一個(gè)線程可以創(chuàng)建和撤銷另一個(gè)線程;
進(jìn)程和線程的關(guān)系:
(1)一個(gè)線程只能屬于一個(gè)進(jìn)程,而一個(gè)進(jìn)程可以有多個(gè)線程,但至少有一個(gè)線程。
(2)資源分配給進(jìn)程,同一進(jìn)程的所有線程共享該進(jìn)程的所有資源。
(3)線程在執(zhí)行過程中,需要協(xié)作同步。不同進(jìn)程的線程間要利用消息通信的辦法實(shí)現(xiàn)同步。
(4)處理機(jī)分給線程,即真正在處理機(jī)上運(yùn)行的是線程。
(5)線程是指進(jìn)程內(nèi)的一個(gè)執(zhí)行單元,也是進(jìn)程內(nèi)的可調(diào)度實(shí)體。
線程與進(jìn)程的區(qū)別:
(1)調(diào)度:線程作為調(diào)度和分配的基本單位,進(jìn)程作為擁有資源的基本單位。
(2)并發(fā)性:不僅進(jìn)程之間可以并發(fā)執(zhí)行,同一個(gè)進(jìn)程的多個(gè)線程之間也可以并發(fā)執(zhí)行。
(3)擁有資源:進(jìn)程是擁有資源的一個(gè)獨(dú)立單位,線程不擁有系統(tǒng)資源,但可以訪問隸屬于進(jìn)程的資源。
(4)系統(tǒng)開銷:在創(chuàng)建或撤銷進(jìn)程的時(shí)候,由于系統(tǒng)都要為之分配和回收資源,導(dǎo)致系統(tǒng)的開銷明顯大于創(chuàng)建或撤銷線程時(shí)的開銷。但進(jìn)程有獨(dú)立的地址空間,進(jìn)程崩潰后,在保護(hù)模式下不會(huì)對(duì)其他的進(jìn)程產(chǎn)生影響,而線程只是一個(gè)進(jìn)程中的不同的執(zhí)行路徑。線程有自己的堆棧和局部變量,但線程之間沒有單獨(dú)的地址空間,一個(gè)線程死掉就等于整個(gè)進(jìn)程死掉,所以多進(jìn)程的程序要比多線程的程序健壯,但是在進(jìn)程切換時(shí),耗費(fèi)的資源較大,效率要差些。
創(chuàng)建一個(gè)線程(Java中提供了三種創(chuàng)建線程的方法):
通過實(shí)現(xiàn)Runnable接口;
通過繼承Thread類本身;
通過Callable和Future創(chuàng)建線程。
一、通過實(shí)現(xiàn)Runnable接口來創(chuàng)建線程(推薦使用)
實(shí)現(xiàn)Java.lang.Runnable接口,并重寫run()方法。
優(yōu)勢(shì):可繼承其它類,多線程可共享同一個(gè)Thread對(duì)象;
劣勢(shì):編程方式稍微復(fù)雜,如需訪問當(dāng)前線程,需調(diào)用Thread.currentThread()方法。
package結(jié)果:
main線程 main線程 Thread-0線程 main線程 Thread-0線程 main線程 Thread-0線程 main線程 Thread-0線程 Thread-0線程二、通過繼承Thread類本身來創(chuàng)建線程(不推薦使用==>Java中單繼承的局限性)
繼承Java.lang.Thread類,并覆蓋run() 方法。
優(yōu)勢(shì):編寫簡(jiǎn)單;
劣勢(shì):無法繼承其它父類
package com.bjwyj.thread; /*** 創(chuàng)建線程二:* 1、繼承Thread+重寫run* 2、啟動(dòng):創(chuàng)建子類對(duì)象+start* @author 吳永吉**/ public class ThreadDemo02 extends Thread{/*** 線程入口點(diǎn)*/@Overridepublic void run() {for(int i=0;i<5;i++) {System.out.println(Thread.currentThread().getName()+"線程");}}public static void main(String[] args) {//創(chuàng)建子類對(duì)象ThreadDemo02 td = new ThreadDemo02();//啟動(dòng)td.start(); //不保證立即運(yùn)行,CPU調(diào)用for(int i=0;i<5;i++) {System.out.println(Thread.currentThread().getName()+"線程");}} }結(jié)果:
Thread-0線程 main線程 main線程 Thread-0線程 main線程 Thread-0線程 Thread-0線程 Thread-0線程 main線程 main線程三、通過Callable和Future創(chuàng)建線程(屬于JUC高級(jí)編程,初學(xué)者了解即可)
實(shí)現(xiàn)Callable接口,重寫call方法。
優(yōu)勢(shì):性能更優(yōu)。
劣勢(shì):編寫復(fù)雜。
package com.bjwyj.thread;import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future;/*** 了解創(chuàng)建線程的方式三* @author 吳永吉**/ public class ThreadDemo03 implements Callable<String>{String name; //名字public ThreadDemo03(String name) {this.name = name;}@Overridepublic String call() throws Exception {return this.name;}public static void main(String[] args) throws InterruptedException, ExecutionException {ThreadDemo03 td1 = new ThreadDemo03("線程1");ThreadDemo03 td2 = new ThreadDemo03("線程2");ThreadDemo03 td3 = new ThreadDemo03("線程3");//創(chuàng)建執(zhí)行服務(wù)ExecutorService ser = Executors.newFixedThreadPool(3);//提交任務(wù)Future<String> result1 = ser.submit(td1);Future<String> result2 = ser.submit(td2);Future<String> result3 = ser.submit(td3);//獲取結(jié)果String r1 = result1.get();String r2 = result2.get();String r3 = result3.get();System.out.println(r1);System.out.println(r2);System.out.println(r3);//關(guān)閉服務(wù)ser.shutdownNow();} }結(jié)果:
線程1 線程2 線程3從以上方式一和方式二可以看出:各個(gè)線程之間幾乎是穿插著運(yùn)行并輸出的,那么,多線程情況下,難道真的是同時(shí)在運(yùn)行嗎?答案不是絕對(duì)的。首先,一個(gè)處理器(CPU)在某一個(gè)時(shí)間點(diǎn)上永遠(yuǎn)都只能是一個(gè)線程!雙核CPU可以理解為兩塊CPU,4核,8核等依次類推,就單個(gè)CPU而言,某個(gè)時(shí)間點(diǎn)只能是一個(gè)線程在運(yùn)行,所謂的多線程是通過調(diào)度獲取CPU的時(shí)間片實(shí)現(xiàn)的。其實(shí)就相當(dāng)于CPU是一個(gè)人,多線程是幾件事,CPU一下子干這件事,干一會(huì)時(shí)間片到了就干另一件。由于CPU計(jì)算速度很快很快,所以看起來就像是幾件事情在同時(shí)做著。不過現(xiàn)在CPU都是雙核四核八核的,這些是真的一起干的,因?yàn)檫@是幾個(gè)人干幾件事,所以,多CPU當(dāng)然是真多線程。
線程是一個(gè)動(dòng)態(tài)執(zhí)行的過程,它也有一個(gè)從產(chǎn)生到死亡的過程,線程生命周期有五種狀態(tài):
新建(new Thread)
當(dāng)創(chuàng)建Thread類的一個(gè)實(shí)例(對(duì)象)時(shí),此線程進(jìn)入新建狀態(tài)(未被啟動(dòng))。
例如:Thread t1=new Thread();
就緒(runnable)
線程已經(jīng)被啟動(dòng),正在等待被分配給CPU時(shí)間片,也就是說此時(shí)線程正在就緒隊(duì)列中排隊(duì)等候得到CPU資源。
例如:t1.start();
運(yùn)行(running)
線程獲得CPU資源正在執(zhí)行任務(wù)(run()方法),此時(shí)除非此線程自動(dòng)放棄CPU資源或者有優(yōu)先級(jí)更高的線程進(jìn)入,線程將一直運(yùn)行到結(jié)束。
死亡(dead)
當(dāng)線程執(zhí)行完畢或被其它線程殺死,線程就進(jìn)入死亡狀態(tài),這時(shí)線程不可能再進(jìn)入就緒狀態(tài)等待執(zhí)行。
自然終止:正常運(yùn)行run()方法后終止。
異常終止:調(diào)用stop()(已棄用)方法讓一個(gè)線程終止運(yùn)行。
堵塞(blocked)
由于某種原因?qū)е抡谶\(yùn)行的線程讓出CPU并暫停自己的執(zhí)行,即進(jìn)入堵塞狀態(tài)。
正在睡眠:用sleep(long t) 方法可使線程進(jìn)入睡眠方式。一個(gè)睡眠著的線程在指定的時(shí)間過去可進(jìn)入就緒狀態(tài)。
正在等待:調(diào)用wait()方法。(調(diào)用notify()方法回到就緒狀態(tài))
被另一個(gè)線程所阻塞:調(diào)用suspend()(已棄用)方法。(調(diào)用resume()(已棄用)方法恢復(fù))
總結(jié)
以上是生活随笔為你收集整理的多线程java_Java多线程基础的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: jar包导出无法显示图片或者音乐_音乐曲
- 下一篇: 三丰三坐标编程基本步骤_数控车床编程,经