摘要:一個進程中是可以有多個線程的,這個應(yīng)用程序也可以稱之為多線程程序。也就是說線程創(chuàng)建并執(zhí)行需要給定線程要執(zhí)行的任務(wù)。接口對線程對象和線程任務(wù)進行解耦。另外,通過適當?shù)恼{(diào)整線程中的線程數(shù)目可以防止出現(xiàn)資源不足的情況。
01進程概念
*A:進程概念
*a:進程:進程指正在運行的程序。確切的來說,當一個程序進入內(nèi)存運行,
即變成一個進程,進程是處于運行過程中的程序,并且具有一定獨立功能。02線程的概念
*A:線程的概念
*a:線程:線程是進程中的一個執(zhí)行單元(執(zhí)行路徑),負責當前進程中程序的執(zhí)行,
一個進程中至少有一個線程。一個進程中是可以有多個線程的, 這個應(yīng)用程序也可以稱之為多線程程序。 簡而言之:一個程序運行后至少有一個進程,一個進程中可以包含多個線程03深入線程的概念
A:深入線程的概念
什么是多線程呢? 即就是一個程序中有多個線程在同時執(zhí)行。 一個核心的CPU在多個線程之間進行著隨即切換動作,由于切換時間很短(毫秒甚至是納秒級別),導(dǎo)致我們感覺不出來 單線程程序:即,若有多個任務(wù)只能依次執(zhí)行。當上一個任務(wù)執(zhí)行結(jié)束后,下一個任務(wù)開始執(zhí)行。如去 網(wǎng)吧上網(wǎng),網(wǎng)吧只能讓一個人上網(wǎng),當這個人下機后,下一個人才能上網(wǎng)。 多線程程序:即,若有多個任務(wù)可以同時執(zhí)行。如,去網(wǎng)吧上網(wǎng),網(wǎng)吧能夠讓多個人同時上網(wǎng)。04迅雷的多線程下載
A:迅雷的多線程下載
多線程,每個線程都讀一個文件05線程的運行模式
A:線程的運行模式
a:分時調(diào)度 所有線程輪流使用 CPU 的使用權(quán),平均分配每個線程占用 CPU 的時間。 b:搶占式調(diào)度 優(yōu)先讓優(yōu)先級高的線程使用 CPU,如果線程的優(yōu)先級相同,那么會隨機選擇一個(線程隨機性),Java使用的為搶占式調(diào)度。 大部分操作系統(tǒng)都支持多進程并發(fā)運行,現(xiàn)在的操作系統(tǒng)幾乎都支持同時運行多個程序。比如:現(xiàn)在我們上課一邊使用編輯器,一邊使用錄屏軟件,同時還開著畫圖板,dos窗口等軟件。此時,這些程序是在同時運行,”感覺這些軟件好像在同一時刻運行著“。 實際上,CPU(中央處理器)使用搶占式調(diào)度模式在多個線程間進行著高速的切換。對于CPU的一個核而言,某個時刻,只能執(zhí)行一個線程,而 CPU的在多個線程間切換速度相對我們的感覺要快,看上去就是在同一時刻運行。 其實,多線程程序并不能提高程序的運行速度,但能夠提高程序運行效率,讓CPU的使用率更高。06main的主線程
*A:main的主線程
/* * 程序中的主線程 */ public class Demo { public static void main(String[] args) { System.out.println(0/0); function(); System.out.println(Math.abs(-9)); } public static void function(){ for(int i = 0 ; i < 10000;i++){ System.out.println(i); } } }
=======================第二節(jié)課開始=============================================
07Thread類介紹A:Thread類介紹:Thread是程序中的執(zhí)行線程。Java 虛擬機允許應(yīng)用程序并發(fā)地運行多個執(zhí)行線程。
發(fā)現(xiàn)創(chuàng)建新執(zhí)行線程有兩種方法。 ?a:一種方法是將類聲明為 Thread 的子類。該子類應(yīng)重寫 Thread 類的 run 方法。創(chuàng)建對象,開啟線程。run方法相當于其他線程的main方法。 ?b:另一種方法是聲明一個實現(xiàn) Runnable 接口的類。該類然后實現(xiàn) run 方法。然后創(chuàng)建Runnable的子類對象,傳入到某個線程的構(gòu)造方法中,開啟線程。08實現(xiàn)線程程序繼承Thread
*A:實現(xiàn)線程程序繼承Thread
/* * 創(chuàng)建和啟動一個線程 * 創(chuàng)建Thread子類對象 * 子類對象調(diào)用方法start() * 讓線程程序執(zhí)行,JVM調(diào)用線程中的run */ public class ThreadDemo { public static void main(String[] args) { SubThread st = new SubThread(); SubThread st1 = new SubThread(); st.start(); st1.start(); for(int i = 0; i < 50;i++){ System.out.println("main..."+i); } } } /* * 定義子類,繼承Thread * 重寫方法run */ public class SubThread extends Thread{ public void run(){ for(int i = 0; i < 50;i++){ System.out.println("run..."+i); } } }09線程執(zhí)行的隨機性
*A:線程執(zhí)行的隨機性
/* 代碼分析: 整個程序就只有三個線程, 一個是主線程 啟動另外兩個線程 st.start(); st1.start(); for(int i = 0; i < 50;i++){ System.out.println("main..."+i); } 一個是st(Thread-0)線程 for(int i = 0; i < 50;i++){ System.out.println("run..."+i); } 一個是st1(Thread-1)線程下 */ public class ThreadDemo { public static void main(String[] args) { SubThread st = new SubThread(); SubThread st1 = new SubThread(); st.start(); st1.start(); for(int i = 0; i < 50;i++){ System.out.println("main..."+i); } } } /* * 定義子類,繼承Thread * 重寫方法run */ public class SubThread extends Thread{ public void run(){ for(int i = 0; i < 50;i++){ System.out.println("run..."+i); } } }10為什么要繼承Thread
*A:什么要繼承Thread
a:我們?yōu)槭裁匆^承Thread類,并調(diào)用其的start方法才能開啟線程呢? 繼承Thread類:因為Thread類用來描述線程,具備線程應(yīng)該有功能。那為什么不直接創(chuàng)建Thread類的對象呢? 如下代碼: Thread t1 = new Thread(); t1.start();//這樣做沒有錯,但是該start調(diào)用的是Thread類中的run方法 //而這個run方法沒有做什么事情,更重要的是這個run方法中并沒有定義我們需要讓線程執(zhí)行的代碼。 b:創(chuàng)建線程的目的是什么? 是為了建立程序多帶帶的執(zhí)行路徑,讓多部分代碼實現(xiàn)同時執(zhí)行。也就是說線程創(chuàng)建并執(zhí)行需要給定線程要執(zhí)行的任務(wù)。 對于之前所講的主線程,它的任務(wù)定義在main函數(shù)中。自定義線程需要執(zhí)行的任務(wù)都定義在run方法中。11多線程內(nèi)存圖解
*A:多線程內(nèi)存圖解
多線程執(zhí)行時,到底在內(nèi)存中是如何運行的呢? 多線程執(zhí)行時,在棧內(nèi)存中,其實每一個執(zhí)行線程都有一片自己所屬的棧內(nèi)存空間。進行方法的壓棧和彈棧。 當執(zhí)行線程的任務(wù)結(jié)束了,線程自動在棧內(nèi)存中釋放了。但是當所有的執(zhí)行線程都結(jié)束了,那么進程就結(jié)束了。
=======================第三節(jié)課開始=============================================
12獲取線程名字Thread類方法getName*A:獲取線程名字Thread類方法getName
/* * 獲取線程名字,父類Thread方法 * String getName() */ public class NameThread extends Thread{ public NameThread(){ super("小強"); } public void run(){ System.out.println(getName()); } } /* * 每個線程,都有自己的名字 * 運行方法main線程,名字就是"main" * 其他新鍵的線程也有名字,默認 "Thread-0","Thread-1" * * JVM開啟主線程,運行方法main,主線程也是線程,是線程必然就是 * Thread類對象 */ public class ThreadDemo { public static void main(String[] args) { NameThread nt = new NameThread(); nt.start(); } }13獲取線程名字Thread類方法currentThread
*A:獲取線程名字Thread類方法currentThread
/*
* 獲取線程名字,父類Thread方法 * String getName() */
public class NameThread extends Thread{
public void run(){ System.out.println(getName()); }
}
/*
* 每個線程,都有自己的名字 * 運行方法main線程,名字就是"main" * 其他新鍵的線程也有名字,默認 "Thread-0","Thread-1" * * JVM開啟主線程,運行方法main,主線程也是線程,是線程必然就是 * Thread類對象 * Thread類中,靜態(tài)方法 * static Thread currentThread()返回正在執(zhí)行的線程對象 */
public class ThreadDemo {
public static void main(String[] args) { NameThread nt = new NameThread(); nt.start(); /*Thread t =Thread.currentThread(); System.out.println(t.getName());*/ System.out.println(Thread.currentThread().getName());
}
}
14線程名字設(shè)置A:線程名字設(shè)置
/* * 獲取線程名字,父類Thread方法 * String getName() */ public class NameThread extends Thread{ public NameThread(){ super("小強"); } public void run(){ System.out.println(getName()); } } /* * 每個線程,都有自己的名字 * 運行方法main線程,名字就是"main" * 其他新鍵的線程也有名字,默認 "Thread-0","Thread-1" * * JVM開啟主線程,運行方法main,主線程也是線程,是線程必然就是 * Thread類對象 * Thread類中,靜態(tài)方法 * static Thread currentThread()返回正在執(zhí)行的線程對象 */ public class ThreadDemo { public static void main(String[] args) { NameThread nt = new NameThread(); nt.setName("旺財"); nt.start(); } }15Thread類方法sleep
A:Thread類方法sleep
public class ThreadDemo { public static void main(String[] args) throws Exception{ /*for(int i = 0 ; i < 5 ;i++){ Thread.sleep(50); System.out.println(i); }*/ new SleepThread().start(); } } public class SleepThread extends Thread{ public void run(){ for(int i = 0 ; i < 5 ;i++){ try{ Thread.sleep(500);//睡眠500ms,500ms已到并且cpu切換到該線程繼續(xù)向下執(zhí)行 }catch(Exception ex){ } System.out.println(i); } } }16實現(xiàn)線程的另一種方式實現(xiàn)Runnable接口
A:實現(xiàn)線程的另一種方式實現(xiàn)Runnable接口
/* * 實現(xiàn)接口方式的線程 * 創(chuàng)建Thread類對象,構(gòu)造方法中,傳遞Runnable接口實現(xiàn)類 * 調(diào)用Thread類方法start() */ public class ThreadDemo { public static void main(String[] args) { SubRunnable sr = new SubRunnable(); Thread t = new Thread(sr); t.start(); for(int i = 0 ; i < 50; i++){ System.out.println("main..."+i); } } } /* * 實現(xiàn)線程成功的另一個方式,接口實現(xiàn) * 實現(xiàn)接口Runnable,重寫run方法 */ public class SubRunnable implements Runnable{ public void run(){ for(int i = 0 ; i < 50; i++){ System.out.println("run..."+i); } } }17實現(xiàn)接口方式的好處
A:實現(xiàn)接口方式的好處 第二種方式實現(xiàn)Runnable接口避免了單繼承的局限性,所以較為常用。 實現(xiàn)Runnable接口的方式,更加的符合面向?qū)ο?,線程分為兩部分,一部分線程對象,一部分線程任務(wù)。 繼承Thread類,線程對象和線程任務(wù)耦合在一起。 一旦創(chuàng)建Thread類的子類對象,既是線程對象,有又有線程任務(wù)。 實現(xiàn)runnable接口,將線程任務(wù)多帶帶分離出來封裝成對象,類型就是Runnable接口類型。Runnable接口對線程對象和線程任務(wù)進行解耦。 (降低緊密性或者依賴性,創(chuàng)建線程和執(zhí)行任務(wù)不綁定)18匿名內(nèi)部類實現(xiàn)線程程序
*A:匿名內(nèi)部類實現(xiàn)線程程序 /* * 使用匿名內(nèi)部類,實現(xiàn)多線程程序 * 前提: 繼承或者接口實現(xiàn) * new 父類或者接口(){ * 重寫抽象方法 * } */ public class ThreadDemo { public static void main(String[] args) { //繼承方式 XXX extends Thread{ public void run(){}} new Thread(){ public void run(){ System.out.println("!!!"); } }.start(); //實現(xiàn)接口方式 XXX implements Runnable{ public void run(){}} Runnable r = new Runnable(){ public void run(){ System.out.println("###"); } }; new Thread(r).start(); new Thread(new Runnable(){ public void run(){ System.out.println("@@@"); } }).start(); } }
=======================第四節(jié)課開始=============================================
19線程的狀態(tài)圖A:線程的狀態(tài)圖
a:參見線程狀態(tài)圖.jpg20線程池的原理
A:線程池的原理
1.在java中,如果每個請求到達就創(chuàng)建一個新線程,開銷是相當大的。 2.在實際使用中,創(chuàng)建和銷毀線程花費的時間和消耗的系統(tǒng)資源都相當大,甚至可能要比在處理實際的用戶請求的時間和資源要多的多。 3.除了創(chuàng)建和銷毀線程的開銷之外,活動的線程也需要消耗系統(tǒng)資源。 如果在一個jvm里創(chuàng)建太多的線程,可能會使系統(tǒng)由于過度消耗內(nèi)存或“切換過度”而導(dǎo)致系統(tǒng)資源不足。 為了防止資源不足,需要采取一些辦法來限制任何給定時刻處理的請求數(shù)目,盡可能減少創(chuàng)建和銷毀線程的次數(shù),特別是一些資源耗費比較大的線程的創(chuàng)建和銷毀,盡量利用已有對象來進行服務(wù)。 線程池主要用來解決線程生命周期開銷問題和資源不足問題。通過對多個任務(wù)重復(fù)使用線程,線程創(chuàng)建的開銷就被分攤到了多個任務(wù)上了,而且由于在請求到達時線程已經(jīng)存在,所以消除了線程創(chuàng)建所帶來的延遲。這樣,就可以立即為請求服務(wù),使用應(yīng)用程序響應(yīng)更快。另外,通過適當?shù)恼{(diào)整線程中的線程數(shù)目可以防止出現(xiàn)資源不足的情況。21JDK5實現(xiàn)線程池
A:JDK5實現(xiàn)線程池 /* * JDK1.5新特性,實現(xiàn)線程池程序 * 使用工廠類 Executors中的靜態(tài)方法創(chuàng)建線程對象,指定線程的個數(shù) * static ExecutorService newFixedThreadPool(int 個數(shù)) 返回線程池對象 * 返回的是ExecutorService接口的實現(xiàn)類 (線程池對象) * * 接口實現(xiàn)類對象,調(diào)用方法submit (Ruunable r) 提交線程執(zhí)行任務(wù) * */ public class ThreadPoolDemo { public static void main(String[] args) { //調(diào)用工廠類的靜態(tài)方法,創(chuàng)建線程池對象 //返回線程池對象,是返回的接口 ExecutorService es = Executors.newFixedThreadPool(2); //調(diào)用接口實現(xiàn)類對象es中的方法submit提交線程任務(wù) //將Runnable接口實現(xiàn)類對象,傳遞 es.submit(new ThreadPoolRunnable()); es.submit(new ThreadPoolRunnable()); es.submit(new ThreadPoolRunnable()); } } public class ThreadPoolRunnable implements Runnable { public void run(){ System.out.println(Thread.currentThread().getName()+" 線程提交任務(wù)"); } }22實現(xiàn)線程的Callable接口方式
A:實現(xiàn)線程的Callable接口方式
/* * 實現(xiàn)線程程序的第三個方式,實現(xiàn)Callable接口方式 * 實現(xiàn)步驟 * 工廠類 Executors靜態(tài)方法newFixedThreadPool方法,創(chuàng)建線程池對象 * 線程池對象ExecutorService接口實現(xiàn)類,調(diào)用方法submit提交線程任務(wù) * submit(Callable c) */ public class ThreadPoolDemo1 { public static void main(String[] args)throws Exception { ExecutorService es = Executors.newFixedThreadPool(2); //提交線程任務(wù)的方法submit方法返回 Future接口的實現(xiàn)類 Future23線程實現(xiàn)異步計算f = es.submit(new ThreadPoolCallable()); String s = f.get(); System.out.println(s); } } /* * Callable 接口的實現(xiàn)類,作為線程提交任務(wù)出現(xiàn) * 使用方法返回值 */ import java.util.concurrent.Callable; public class ThreadPoolCallable implements Callable { public String call(){ return "abc"; } }
A:線程實現(xiàn)異步計算
/* * 使用多線程技術(shù),求和 * 兩個線程,1個線程計算1+100,另一個線程計算1+200的和 * 多線程的異步計算 */ public class ThreadPoolDemo { public static void main(String[] args)throws Exception { ExecutorService es = Executors.newFixedThreadPool(2); Futuref1 =es.submit(new GetSumCallable(100)); Future f2 =es.submit(new GetSumCallable(200)); System.out.println(f1.get()); System.out.println(f2.get()); es.shutdown(); } } public class GetSumCallable implements Callable { private int a; public GetSumCallable(int a){ this.a=a; } public Integer call(){ int sum = 0 ; for(int i = 1 ; i <=a ; i++){ sum = sum + i ; } return sum; } }
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/67185.html
摘要:線程池維護線程所允許的空閑時間的單位線程池所使用的緩沖隊列一般采用阻塞隊列,有很多種無界阻塞隊列有界阻塞隊列同步移交隊列線程池對拒絕任務(wù)的處理策略丟棄任務(wù)并拋出異常。 一、線程池的概念 池,就是一個工廠,會提前生產(chǎn)出一些東西供使用。所以線程池就是處理多線程的一種方式。其作用就在于:復(fù)用已有資源,控制資源總量 二、為什么使用線程池 如果不使用線程池,那么:(1)使用單線程,但是這種方式吞...
摘要:最后,我們會通過對源代碼的剖析深入了解線程池的運行過程和具體設(shè)計,真正達到知其然而知其所以然的水平。創(chuàng)建線程池既然線程池是一個類,那么最直接的使用方法一定是一個類的對象,例如。單線程線程池單線程線程 我們一般不會選擇直接使用線程類Thread進行多線程編程,而是使用更方便的線程池來進行任務(wù)的調(diào)度和管理。線程池就像共享單車,我們只要在我們有需要的時候去獲取就可以了。甚至可以說線程池更棒,...
摘要:本文只介紹中線程池的基本使用,不會過多的涉及到線程池的原理??删彺婢€程的線程池創(chuàng)建一個可緩存線程的線程池。首先是從接口繼承到的方法使用該方法即將一個任務(wù)交給線程池去執(zhí)行。方法方法的作用是向線程池發(fā)送關(guān)閉的指令。 首先,我們?yōu)槭裁葱枰€程池?讓我們先來了解下什么是 對象池 技術(shù)。某些對象(比如線程,數(shù)據(jù)庫連接等),它們創(chuàng)建的代價是非常大的 —— 相比于一般對象,它們創(chuàng)建消耗的時間和內(nèi)存都...
摘要:在開發(fā)過程中,合理地使用線程池能夠帶來個好處。性質(zhì)不同的任務(wù)可以交給不同規(guī)模的線程池執(zhí)行。當然具體合理線程池值大小,需要結(jié)合系統(tǒng)實際情況,在大量的嘗試下比較才能得出,以上只是前人總結(jié)的規(guī)律。 線程池簡述 Java中的線程池是運用場景最多的并發(fā)框架,幾乎所有需要異步或并發(fā)執(zhí)行任務(wù)的程序都可以使用線程池。在開發(fā)過程中,合理地使用線程池能夠帶來3個好處。 降低資源消耗。通過重復(fù)利用已創(chuàng)建的...
摘要:線程池的工作原理一個線程池管理了一組工作線程,同時它還包括了一個用于放置等待執(zhí)行任務(wù)的任務(wù)隊列阻塞隊列。使用線程池可以對線程進行統(tǒng)一的分配和監(jiān)控。線程池的注意事項雖然線程池是構(gòu)建多線程應(yīng)用程序的強大機制,但使用它并不是沒有風險的。 線程池的工作原理一個線程池管理了一組工作線程, 同時它還包括了一個用于放置等待執(zhí)行 任務(wù)的任務(wù)隊列(阻塞隊列) 。 一個線程池管理了一組工作線程, 同時它還...
摘要:創(chuàng)建線程的方式方式一將類聲明為的子類。將該線程標記為守護線程或用戶線程。其中方法隱含的線程為父線程?;謴?fù)線程,已過時。等待該線程銷毀終止。更多的使當前線程在鎖存器倒計數(shù)至零之前一直等待,除非線 知識體系圖: showImg(https://segmentfault.com/img/bVbef6v?w=1280&h=960); 1、線程是什么? 線程是進程中獨立運行的子任務(wù)。 2、創(chuàng)建線...
閱讀 4561·2021-11-24 10:24
閱讀 1474·2021-11-22 15:22
閱讀 2164·2021-11-17 09:33
閱讀 2553·2021-09-22 15:29
閱讀 574·2019-08-30 15:55
閱讀 1719·2019-08-29 18:42
閱讀 2791·2019-08-29 12:55
閱讀 1838·2019-08-26 13:55