java第八章线程
文章目錄
- 8.1線程概述
- 程序、進程、線程
- 多線程含義
- 8.2線程的創(chuàng)建
- 不管是繼承還是實現(xiàn)創(chuàng)建,在實例化時都可以塞到Thread tread =new Tread(a,"name")里實現(xiàn)變量共享(如下鏈接舉例)
- 繼承Thread創(chuàng)建
- 一定要重寫run方法:
- 實現(xiàn)接口:Runnable創(chuàng)建
- 只要是線程就必須實現(xiàn)接口,實現(xiàn)run方法
- 實現(xiàn)所有方法,但只有run方法
- 封裝
- 好處:創(chuàng)建相同對象,共享類中變量,但此時不同步
- 共享(t2,t3中的a不同)
- 共享靜態(tài)變量,即可同步
- Callable和Future創(chuàng)建
- 先實現(xiàn)接口,并實現(xiàn)方法重寫,
- 10:創(chuàng)建工具類,并從t3中取得call方法的值,實現(xiàn)了相應(yīng)線程的接口
- 11:實現(xiàn)接口,封裝
- 12:執(zhí)行
- 可以獲取返回值,可能等待較長出現(xiàn)異常
- 用get獲取
- 法一 try catch
- 法二:拋出
- summary
- 一些特殊創(chuàng)建寫法 比較
- 匿名內(nèi)部類
- 類的匿名
- 接口匿名實現(xiàn)
- lambda表達式創(chuàng)建線程
- 線程里接受一個函數(shù)表達式
- 常見方法
- 測試類直接繼承線程(一般用來測試)
- 測試類直接實現(xiàn)接口(一般用來測試)
- 8.3線程生命周期
- 8.3.1生命周期描述
- 新建狀態(tài):實例化
- 就緒狀態(tài):創(chuàng)建了線程、得到了資源,得到了除了cpu的所有資源
- 運行狀態(tài):在cpu中運行。(單核只能有一個)
- 分支:阻塞狀態(tài):除了cpu還缺其他資源,不能進行,所以就先失去cpu給別人,你先等著(比如缺打印機)
- 分支:DEAD:異常了、完成了、人為停止
- 分支:回就緒狀態(tài):聽從cpu調(diào)度
- 8.3.2Thread常用方法(怎么實現(xiàn)上圖)
- 啟動
- 讓步方法
- 只讓出一次cpu
- 休眠,暫停
- 可能會產(chǎn)生異常,
- 沒有返回值不能拋出,只能try catch
- 等待線程結(jié)束
- 成對,阻塞,需要同步問題,到時講
- 8.4線程同步
- 線程同步-可見性(非線程安全)
- 可見性:有人改了,其他線程也該知道
- 關(guān)鍵字的使用
- 線程同步-原子性問題
- 另:多個線程共同執(zhí)行同一個方法的情況,線程與runnnable對象
- lock接口
- wait()和notify()
- (sleep是自動喚醒)
- wait是被動喚醒
- sleep休眠不放棄鎖
- wait放棄鎖
- 區(qū)別
- 8.5線程池
- 線程池的概念
- 線程池相關(guān)類
- 這個例子是不是太好了???,難道不會有重復(fù)的id嘛
- 而且主線程和他們之間也有調(diào)度,都在池里?
- 當(dāng)給主線程加上100ms等待:
- [intelliJ idea 使用try/catch 快捷提示](https://blog.csdn.net/ycg33/article/details/90217164)
8.1線程概述
程序、進程、線程
一組靜態(tài)代碼
當(dāng)程序獲得cpu計算資源是不叫程序了,叫進程,動態(tài)的
是永遠有資源的單位
就是一個執(zhí)行機構(gòu)
線程:進程,多對一
對應(yīng)關(guān)系:
進程是分配的獨立單位
線程是調(diào)度執(zhí)行的獨立單位
線程執(zhí)行進程的任務(wù),進程提供資源,組合起來完成任務(wù)
進程和線城是動態(tài)的,進程是擁有資源的單位,作為線程的后盾,線程來執(zhí)行
相同一件事情,分的越多,并發(fā),執(zhí)行效率更高 ,也就是多線程
在java中對線程也進行了封裝,class
id name 優(yōu)先級(cpu調(diào)度)
多線程含義
main是主線程
會創(chuàng)建主線程
模擬QQ聊天和上傳(實際上還是串行,但很快,就像并行)
實際都是主線程進行的:,根本沒并行啊,
希望聊天單獨生成一個線程,用戶角度就并行了
用繼承創(chuàng)建一個自己的新進程類
重寫方法run,要進行什么都寫到run里
下一步在創(chuàng)建聊天線程,并run(執(zhí)行)
失敗了:
不要使用run方法,線程執(zhí)行時會自動調(diào)用,要好多事情呢(資源分配。。。。。)
調(diào)用的話,就是普通調(diào)用普通方法
啟動線程:
效果:(默認(rèn)名)
重置名字:所有屬性都要在 start之前完成:
上傳線程同理:
ONE文件夾下
8.2線程的創(chuàng)建
不管是繼承還是實現(xiàn)創(chuàng)建,在實例化時都可以塞到Thread tread =new Tread(a,“name”)里實現(xiàn)變量共享(如下鏈接舉例)
總結(jié)的很好
繼承Thread創(chuàng)建
線程創(chuàng)建時相關(guān)接口與具體類:
上節(jié)的做法
一定要重寫run方法:
測試:new時未創(chuàng)建,只是實例化一個對象,start時才啟動(分配資源,創(chuàng)建線程,執(zhí)行)
啟動兩次?:異常:只能啟動一次
還可以設(shè)置各種屬性:但要在啟動之前,
優(yōu)先級:在java虛擬機中的優(yōu)先策略,但在cpu中還會自己參考著重新考慮吧
還可以重搞構(gòu)造方法:(不能重搞,但可繼承)
還可獲取當(dāng)前線程的屬性:
兩個寫法,效果一樣:
實現(xiàn)接口:Runnable創(chuàng)建
也沒啥區(qū)別,就是主類 實例化那里注意下
只要是線程就必須實現(xiàn)接口,實現(xiàn)run方法
實現(xiàn)所有方法,但只有run方法
只實現(xiàn)了接口,沒有start方法,要運行就要先封裝
測試類
封裝
名字是new
好處:創(chuàng)建相同對象,共享類中變量,但此時不同步
共享(t2,t3中的a不同)
new的a從100開始,new1的a也從100開始
共享靜態(tài)變量,即可同步
Callable和Future創(chuàng)建
很少用,沒講
Callable,call方法有個返回值
用future接口取返回值:
RunnableFuture同時符合兩個
所以用FutrueTask
V是泛型
要實現(xiàn)抽象方法call
一個接口實現(xiàn)一個接口,又實現(xiàn)一個接口(向上套娃)
先實現(xiàn)接口,并實現(xiàn)方法重寫,
10:創(chuàng)建工具類,并從t3中取得call方法的值,實現(xiàn)了相應(yīng)線程的接口
11:實現(xiàn)接口,封裝
12:執(zhí)行
可以獲取返回值,可能等待較長出現(xiàn)異常
下圖中的return
用get獲取
法一 try catch
法二:拋出
summary
一些特殊創(chuàng)建寫法 比較
java是單繼承的,使用繼承的方式,就無法繼承其他類了,繼承層次就會很深,但接口可以多重,工程中實現(xiàn)接口的會比較多
匿名內(nèi)部類
UI界面開發(fā)有可能會用
類的匿名
接口匿名實現(xiàn)
Thread()中間寫接口
lambda表達式創(chuàng)建線程
線程里接受一個函數(shù)表達式
常見方法
測試類直接繼承線程(一般用來測試)
測試類直接實現(xiàn)接口(一般用來測試)
8.3線程生命周期
8.3.1生命周期描述
進程擁有資源,執(zhí)行調(diào)度
線程執(zhí)行過程,有狀態(tài)轉(zhuǎn)換
新建狀態(tài):實例化
就緒狀態(tài):創(chuàng)建了線程、得到了資源,得到了除了cpu的所有資源
運行狀態(tài):在cpu中運行。(單核只能有一個)
分支:阻塞狀態(tài):除了cpu還缺其他資源,不能進行,所以就先失去cpu給別人,你先等著(比如缺打印機)
分支:DEAD:異常了、完成了、人為停止
分支:回就緒狀態(tài):聽從cpu調(diào)度
8.3.2Thread常用方法(怎么實現(xiàn)上圖)
線程類提供的常用方法
啟動
并不是立即執(zhí)行
讓步方法
并發(fā)
只讓出一次cpu
休眠,暫停
自動休眠與阻塞
可能會產(chǎn)生異常,
沒有返回值不能拋出,只能try catch
等待線程結(jié)束
主線程先結(jié)束了,不合邏輯
這里用了拋出異常
thrad執(zhí)行完,才能往下執(zhí)行
成對,阻塞,需要同步問題,到時講
8.4線程同步
進程是資源的后盾
線程是調(diào)度的單位
Java線程是共享進程中的資源
創(chuàng)建副本
比如A和B都想進行加1操作,原為3,A先將3拷貝,突然失去cpu,B拷貝+1,變4,將4 回寫 到變量1,A重獲的cpu,副本3+1回寫4
最終變量一為4,可希望為5
引出問題:線程同步
第一種解決方案:
線程同步-可見性(非線程安全)
1.立刻
2.強制
3.是所有緩存了該變量的線程中的數(shù)據(jù)清空
可見性:有人改了,其他線程也該知道
驗證:
由stop決定是否結(jié)束:()用環(huán)境變量達到同樣的效果
修改:修改為真:
檢測是否為共享變量(主線程,與testVo)
法二:讓主線程休息2秒再修改:
不結(jié)束了,因為副本已經(jīng)建立起來了,沒通知修改,不可見
關(guān)鍵字的使用
線程同步-原子性問題
之前沒解決()
還是都進行a+1操作
這些指令是可以中斷的
中斷時要保護線程,恢復(fù)是要恢復(fù)
希望不可被中斷
鎖機制:
區(qū)別在鎖的類型:
測試:
看看執(zhí)行f1的線程是誰,并休眠他
希望f1()同時只能被一個訪問
想訪問f1得先有鎖
向t對象要鎖
tt對象和t對象獨立
另:多個線程共同執(zhí)行同一個方法的情況,線程與runnnable對象
tt也在使用f1
t1 執(zhí)行f1,向t要鎖
t2也想要t的鎖,等待
t3向tt要鎖,所以可以執(zhí)行
剛才是鎖住同一個對象
如果對靜態(tài)方法上鎖,那就是整個類的鎖
執(zhí)行時,向類要鎖
保證沒有任何線程干擾
也不是特別公平
方法內(nèi)有些代碼不用鎖
這句話就不用
所以用方法塊
這樣就不知道對類還是對象獲取了
加上本對象要鎖
對t1,t2 互斥
以類獲取鎖
也是以對象獲鎖,因為同一個對象內(nèi)的成員對象才相同
這樣就是類了(t,tt中的object相同)
lock接口
新的鎖機制
實現(xiàn)類
區(qū)別:人為釋放,finally中釋放
老例子了:
要先建立鎖對象
上鎖:
try:
finally
還鎖:
wait()和notify()
阻塞方法,和喚醒方法
(sleep是自動喚醒)
wait是被動喚醒
由object提供
測試類:
新建一個線程,休眠兩秒,繼續(xù)執(zhí)行
在搞一個一樣的
希望一個工作時另一個等待
互斥訪問
想到同步代碼塊
每個都加上同步鎖
對同一對象獲取鎖
兩個都是
希望線程一執(zhí)行-》停止-》二執(zhí)行-》結(jié)束-》線程一
sleep休眠不放棄鎖
wait放棄鎖
線程1(thread0)一直在阻塞
線程2結(jié)束時喚醒1
區(qū)別
obj指上鎖的那個對象
8.5線程池
GC:垃圾回收線程
線程池的概念
整體管理線程的機制,把握創(chuàng)建線程的度
core核心線程池:不能停
其他不工作就撤
沒申請到就異常
有的不銷毀,重新用
線程池相關(guān)類
四個構(gòu)造方法
第一個參數(shù):
簡單線程池類
肥宅憨憨池
會有返回值:
交給她管理
搞五個
max為5,(效果不太好,任務(wù)太短了)
這個例子是不是太好了???,難道不會有重復(fù)的id嘛
不是id的問題
name也會
A1:me:那他是先都加入到線程池然后執(zhí)行的嘛 都在線程池中
me:啊,那就是說5個時,先往里加,然后在線程池里執(zhí)行,10個的時候,先加5個,等有執(zhí)行完了,再往里加,然后10個的那個重了好幾次,就是有后加進去的先執(zhí)行完了
A2:線程池線程復(fù)用原理
eg
pool-1-thread-5
pool-1-thread-4
pool-1-thread-3
pool-1-thread-1
pool-1-thread-5
pool-1-thread-1
pool-1-thread-5
pool-1-thread-2
pool-1-thread-5
pool-1-thread-1
A1:應(yīng)該是對的:我嘗試睡幾秒,睡前睡后分開輸出,但一開始的5個都沒有線程被讓出:
output:
pool-1-thread-2開啦
pool-1-thread-3開啦
pool-1-thread-4開啦
pool-1-thread-5開啦
pool-1-thread-1開啦
pool-1-thread-2停啦2
pool-1-thread-4停啦2
pool-1-thread-2開啦
pool-1-thread-4開啦
pool-1-thread-5停啦2
pool-1-thread-1停啦2
pool-1-thread-5開啦
pool-1-thread-3停啦2
pool-1-thread-1開啦
pool-1-thread-3開啦
pool-1-thread-4停啦2
pool-1-thread-3停啦2
pool-1-thread-1停啦2
pool-1-thread-5停啦2
pool-1-thread-2停啦2
pool-1-thread-1開啦
pool-1-thread-3開啦
pool-1-thread-2開啦
pool-1-thread-5開啦
pool-1-thread-4開啦
pool-1-thread-5停啦2
pool-1-thread-1停啦2
pool-1-thread-4停啦2
pool-1-thread-3停啦2
pool-1-thread-2停啦2
更詭異的情況:
本想看看(這樣發(fā)現(xiàn),是一起加進去的,但等著)
thisloop:0
thisloop:1
thisloop:2
thisloop:3
thisloop:4
thisloop:5
thisloop:6
thisloop:7
thisloop:8
thisloop:9
pool-1-thread-4開啦
pool-1-thread-3開啦
pool-1-thread-1開啦
pool-1-thread-2開啦
pool-1-thread-5開啦
pool-1-thread-3停啦2
pool-1-thread-4停啦2
pool-1-thread-1停啦2
pool-1-thread-2停啦2
pool-1-thread-4開啦
pool-1-thread-2開啦
pool-1-thread-5停啦2
pool-1-thread-5開啦
pool-1-thread-3開啦
pool-1-thread-1開啦
pool-1-thread-4停啦2
pool-1-thread-2停啦2
pool-1-thread-5停啦2
pool-1-thread-1停啦2
pool-1-thread-3停啦2
誤會,是巧合,,,,,,(我以為加上crrunentThread后就五個一起開一起關(guān)了呢)
out1
main thisloop:0
main thisloop:1
main thisloop:2
main thisloop:3
main thisloop:4
main thisloop:5
main thisloop:6
main thisloop:7
main thisloop:8
main thisloop:9
pool-1-thread-3開啦
pool-1-thread-4開啦
pool-1-thread-2開啦
pool-1-thread-5開啦
pool-1-thread-1開啦
pool-1-thread-2停啦2
pool-1-thread-1停啦2
pool-1-thread-4停啦2
pool-1-thread-3停啦2
pool-1-thread-5停啦2
pool-1-thread-2開啦
pool-1-thread-3開啦
pool-1-thread-5開啦
pool-1-thread-4開啦
pool-1-thread-1開啦
pool-1-thread-2停啦2
pool-1-thread-5停啦2
pool-1-thread-3停啦2
pool-1-thread-4停啦2
pool-1-thread-1停啦2
out2
main thisloop:0
main thisloop:1
main thisloop:2
main thisloop:3
main thisloop:4
main thisloop:5
main thisloop:6
main thisloop:7
main thisloop:8
main thisloop:9
pool-1-thread-4開啦
pool-1-thread-2開啦
pool-1-thread-5開啦
pool-1-thread-1開啦
pool-1-thread-3開啦
pool-1-thread-2停啦2
pool-1-thread-2開啦
pool-1-thread-5停啦2
pool-1-thread-3停啦2
pool-1-thread-5開啦
pool-1-thread-4停啦2
pool-1-thread-4開啦
pool-1-thread-1停啦2
pool-1-thread-1開啦
pool-1-thread-3開啦
pool-1-thread-2停啦2
pool-1-thread-5停啦2
pool-1-thread-4停啦2
pool-1-thread-1停啦2
pool-1-thread-3停啦2
而且主線程和他們之間也有調(diào)度,都在池里?
main thisloop:0
main thisloop:1
main thisloop:2
main thisloop:3
main thisloop:4
main thisloop:5
main thisloop:6
main thisloop:7
main thisloop:8
pool-1-thread-1開啦
pool-1-thread-4開啦
pool-1-thread-2開啦
main thisloop:9
pool-1-thread-5開啦
pool-1-thread-3開啦
pool-1-thread-4停啦2
pool-1-thread-5停啦2
pool-1-thread-2停啦2
pool-1-thread-1停啦2
pool-1-thread-4開啦
pool-1-thread-3停啦2
pool-1-thread-3開啦
pool-1-thread-2開啦
pool-1-thread-1開啦
pool-1-thread-5開啦
pool-1-thread-4停啦2
pool-1-thread-3停啦2
pool-1-thread-1停啦2
pool-1-thread-5停啦2
pool-1-thread-2停啦2
當(dāng)給主線程加上100ms等待:
import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;public class Main {public static void main(String[] args) {// System.out.println(121212)ExecutorService executorService = Executors.newFixedThreadPool(5);for (int i=0;i<10;i++){System.out.println(Thread.currentThread().getName()+" thisloop:"+i);try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}executorService.submit(new Runnable() {@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+"開啦");try {Thread.sleep(1000);} catch (InterruptedException e) {System.out.println(Thread.currentThread().getName()+"停啦error");e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"停啦2");}});}} }main thisloop:0 main thisloop:1 pool-1-thread-1開啦 main thisloop:2 pool-1-thread-2開啦 main thisloop:3 pool-1-thread-3開啦 main thisloop:4 pool-1-thread-4開啦 main thisloop:5 pool-1-thread-5開啦 main thisloop:6 main thisloop:7 main thisloop:8 main thisloop:9 pool-1-thread-1停啦2 pool-1-thread-1開啦 pool-1-thread-2停啦2 pool-1-thread-2開啦 pool-1-thread-3停啦2 pool-1-thread-3開啦 pool-1-thread-4停啦2 pool-1-thread-4開啦 pool-1-thread-5停啦2 pool-1-thread-5開啦 pool-1-thread-1停啦2 pool-1-thread-2停啦2 pool-1-thread-3停啦2 pool-1-thread-4停啦2 pool-1-thread-5停啦2intelliJ idea 使用try/catch 快捷提示
總結(jié)
- 上一篇: 第一部分 JavaScript语言核心(
- 下一篇: ftp限制