日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

dya19第十章线程

發布時間:2023/12/20 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 dya19第十章线程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

線程


1.程序 、進程和線程
程序: 靜態代碼,為了完成某種功能,使用某種計算機語言編寫的指令集合;
進程:運行中的程序,被加載到內存中,分配資源
線程:進程可以進一步被細化為線程,就是一個具體的執行任務,是操作系統調度中最小的單位

線程和進程的關系:
每一個進程都有相應的線程;在執行程序時,實際上是執行相應的一系列線程,進程是資源分配的最小單位,線程是程序執行的最小單位;[一個進程可以包含多個線程,一個線程只能屬于一個進程,線程不能脫離進程而獨立,也就是說當進程被關閉時,線程也會被自動關閉,每一個進程中至少包含一個線程,也就是主線程,在主線程中開始執行程序,java的程序的入口main()方法就是在主線程中被執行的,在主線程中可以創建并啟動其他線程, 一個進程內的所有線程共享該進程的內存資源。]

創建一個線程:
方式一:繼承Thread類;
方式二:繼承Runnable接口;
**繼承方式和實現方式的區別與聯系
區別: 繼承Thread:線程代碼存放在Thread子類run方法中。
實現Runnable:線程代碼在接口的子類run方法中;
**
實現Runnable的好處
1.避免了單繼承的局限性,提高了擴展性,
2.多個線程可以共享一個接口實現類的對象,非常適合多個相同的線程來處理同一份資源;

public class MyThread implements Runnable{@Overridepublic void run() {for (int i = 0; i < 100; i++) {System.out.println(Thread.currentThread().getName()+i);}} } public class Test{ public static void main(String[] args){ MyThread myThread =new MyThread();//新建一個執行任務 myThread.start()//創建一個線程,并為線程指定執行任務 for(i=0;i<100;i++){ System.out.println(i);}}} package day17.demo3; public class Test{//線程要執行的任務public static void main(String[] args) {MyThread myThread = new MyThread();myThread.start();//創建線程,并為線程指定執行任務for (int i = 0; i < 1000; i++) {System.out.println(i);}} } package day17.demo3; public class MyThread extends Thread {public void run() {for (int i = 0; i < 1000; i++) {System.out.println("main" + i);}}}

Thread中的方法:

Thread() 創建一個新的線程Thread(String name)創建一個指定名字的線程

Thread類中的一些方法

**void Start() 啟動線程****final void setName(String name) 設置線程名稱****final Striing getName() 獲得線程名稱****final void setPriority(int newpriority) 設置線程優先級**線程優先級大的執行的優先權高,(并不是一直執行到完)**final int getPriority() 獲得線程優先級**final void jion() 等待程序終止**也就是說在使用這個方法之后的程序需要等待這個進程完成(死亡)后才能執行**static Thread currentThtead() 返回對當前執行對象的引用**Thread currentThread().getName() 可以獲得當前正在執行的這個程序的名字;**static void sleep(long millis) 讓線程休眠指定時間****Thread yield() 線程讓步(線程從運行態直接轉為就緒態)**stop() 停止程序**本質上不安全,已棄用 package day17.demo4; public class MyThread implements Runnable{@Overridepublic void run() {for (int i = 0; i < 100; i++) {System.out.println(Thread.currentThread().getName()+i);}} } package day17.demo4; public class Test1 {public static void main(String[] args) {MyThread myThread=new MyThread();//新建一個執行任務Thread thread1=new Thread(myThread,"thread1 ");//后面的參數為線程名稱Thread thread2=new Thread(myThread,"thread2 ");//獲得當前線程的線程名稱;currentThread():獲得當前線程;getName():獲取線程名稱;thread1.start();thread2.start();/** 時間片:給線程分配時間單位去執行;* 搶占式:高優先級的線程有更多的執行權,但也不是說低優先級的就沒有機會;具體得看cup對進程的調度;* *///thread1.getPriority()獲取thread1的線程優先級,一般為1-10;默認優先級為5thread1.setPriority(10);//設置線程優先級(高優先級的不一定先制性其優先權高,但不是一直執行完)thread2.setPriority(1);System.out.println("thread1的線程優先級為:"+thread1.getPriority());System.out.println("thread2的線程優先級為:"+thread2.getPriority());} }

線程的優先級:

事實上,計算機只有一個cpu,各個線程輪流獲得cpu的使用權,執行任務;優先級高的線程有更多的被cpu執行的機會;反之則亦然;優先級是用整數表示的,取值范圍為1--10,在通常情況下,優先級默認為5;但可以通過final void setPriority(int newpriority) final int getPriority() 兩個方法來設置以及獲得優先級;調度策略:時間片:給線程分配時間去執行;搶占式:高優先級的線程有更高的 執行權,(但不是說低優先級的程序就沒有機會) Thread類有三個靜態常量來表示優先級 MAX_PRIORITTY:取值為10,表示最高的優先級;MIN_PRIORITY:取值為1,表示最低的優先級;NORM_PRIORITY;取值為5,表示默認的優先級;

線程的狀態

線程在他的生命周期中會處于不同的狀態;
線程的生命周期: 從生到死;

線程的各狀態概念:
新建:當一個Thread類或其子類的對象被聲明并創建時,新生的線程對象處于新建狀態
就緒:處于新建狀態的線程被statr()后,將進入到線程隊列等到cpu的時間片,此時其已經具備了運行的條件,只是沒有被分配到cpu資源;
運行:當就緒的線程被調度并且得到了cpu的資源,便進入運行的狀態,run()方法定義了線程的操作和功能;
阻塞:在某種特殊情況下,被人為掛起或執行輸入輸出操作時,讓出cpu并臨時終止自己的執行,進入阻塞狀態;
死亡:線程完成了它的全部工作或者被線程提前強制性的終止或出現異常導致結束;

線程的分類

Java中的線程主要分為兩類,一類為用戶線程,一類為守護線程;
用個比較通俗的比較就是說是守護線程就是用戶線程的保姆,一般情況下只有當用戶線程全部結束時,時守護線程才能停止;
守護線程的作用:是為其他線程運行提供便利服務,守護線程最典型的應用就是GC(垃圾回收器),它就是一個很稱職的守護者;
用戶線程與守護者線程兩者之間幾乎沒有區別,唯一不同的之處就是虛擬機的離開,如果用戶線程已經全部退出運行了,只剩下守護線程存在了,虛擬機也就退出了,因為沒有了被守護者,守護者線程也就沒有工作可以做了,也就沒有繼續運行程序的必要了,

注意:設置線程為守護線程必須在啟動線程之前,否則可能會拋出一個IllegalThreadStateException異常。

多線程的概念

多線程是指程序中包含多個執行單元,即在一個程序中可以同時運行多個不同的線程來執行不同的任務,也就是說允許單個程序創建多個并行執行的線程來完成各自的任務。
何時需要多線程

1.程序需要同時執行兩個或多個任務。2.程序需要實現一些需要等待的任務時,如用戶輸出、文件讀寫操作或者網絡操作以及搜索等等;3.需要一些后臺運行的程序時。

多線程的優點

提高程序的響應;提高cpu的利用率;改善程序結構,將復雜任務分為多個線程,獨立運行;

多線程的缺點

線程也是程序,所以線程需要占用內存,線程越多占用的內存也越多(升級硬件設備來解決)多線程需要協調和管理,所以需要cpu時刻跟蹤線程;線程之間對共享資源的訪問會相互影響,必須解決競用共享資源的問題;

線程的同步

并發與并行

并行:多個cpu同時執行多個任務,比如,多個人同時做不同的事;并發:一個cpu(采用時間片)同時執行多個任務,比如:秒殺,搶票,多個人做同一件事;

多線程同步

多個線程同時讀寫同一份共享資源時,可能會引起沖突,所以引入線程"同步"機制,即各線程間要有先來后到;

同步就是排隊加鎖:

幾個線程之間要排隊,一個個對共享資源進行操作,而不是同時進行操作; 為了保證數據在方法中被訪問時的正確性,在訪問時加入鎖機制;

模擬買票

兩個窗口分別售票,票數為十張;分別使用繼承Thread類和實現Runnable接口兩種方式實現

確保一個時間點只有一個線程訪問共享資源,可以給共享資源加一把鎖,哪個線程獲取了這把鎖,才有權力訪問該共享資源。

同步監視器

同步監視器可以是任何對象,必須唯一,保證多個線程獲得的是同一個對象(鎖)

同步監視器的執行過程

1.第一個線程訪問,鎖定同步監視器,執行其中的代碼。2.第二個線程訪問,發現同步監視器被鎖定,無法訪問。3.第一個線程訪問完畢,解鎖同步監視器。4.第二個線程訪問,發現同步監視器沒有鎖,然后鎖定并訪問。

一個線程持有鎖會導致其他所有需要此鎖的線程掛起;在多線程競爭下,加鎖與釋放鎖會導致比較多的上下文切換和調度延時,引起性能問題。

synchronized

案例:
模擬兩個窗口同時出售100張票
代碼如下:(繼承Thread類 給代碼塊加同步鎖)

package Day18.demo1; public class SPThread extends Thread {static int num = 100;//定義一個票數static Object obj = new Object();//保證只有一個@Overridepublic void run() {while (true) {//synchronized同步鎖就是一個對象,但要求只有一個synchronized (obj) {if (num > 0) {try {Thread.sleep(100);//讓線程休眠100ms;} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + "出票" + num);num--;} else {break;}}//同步代碼塊,執行完成后,同步對象(鎖)會自動釋放}} } package Day18.demo1; public class Test {public static void main(String[] args) throws InterruptedException {SPThread ck1=new SPThread();ck1.setName("窗口一");SPThread ck2=new SPThread();ck2.setName("窗口二");ck1.start();ck2.start();} }


同樣的案例:
模擬兩個窗口同時出售100張票
代碼如下:(繼承Thread類 給方法加同步鎖)

package Day18.demo1; public class SPThread1 extends Thread{/*將方法上同步鎖*/ static int num=100;@Overridepublic void run() {while (true){if (num>0){try {print();} catch (InterruptedException e) {e.printStackTrace();}}else {break;}}}public synchronized static void print() throws InterruptedException {Thread.sleep(500);if (num>0){System.out.println(Thread.currentThread().getName()+num);num--;}} } package Day18.demo1;import Day18.demo1.SPThread1;public class Test1 {public static void main(String[] args) {SPThread1 t1=new SPThread1();t1.setName("窗口一");SPThread1 t2=new SPThread1();t2.setName("窗口二");t1.start();t2.start();} }


同樣下面用Runnable接口來實現:
代碼如下:(實現Runnable接口, 代碼塊加同步鎖)

package Day18.demo2; public class SpThread implements Runnable {int num = 100;//定義票數@Overridepublic void run() {while (true) {synchronized (this) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}if (num > 0) {System.out.println(Thread.currentThread().getName() + num);num--;} else {break;}}}}} package Day18.demo2; public class Test {public static void main(String[] args) {SpThread spThread=new SpThread();//創建一個任務Thread t1=new Thread(spThread,"窗口一");Thread t2=new Thread(spThread,"窗口二");t1.start();t2.start();} }


代碼如下:(實現Runnable接口, 給方法加同步鎖)

package Day18.demo2;public class SpThread1 implements Runnable{int num=100;@Overridepublic void run() {while (true){if (num>0){try {print();} catch (InterruptedException e) {e.printStackTrace();}}else {break;}}}public synchronized void print() throws InterruptedException {Thread.sleep(200);if (num>0){System.out.println(Thread.currentThread().getName()+num);num--;}} } package Day18.demo2; public class Test1 {public static void main(String[] args) {SpThread1 spThread1=new SpThread1();Thread t1=new Thread(spThread1,"窗口一");Thread t2=new Thread(spThread1,"窗口二");t1.start();t2.start();} }

Lock(鎖)

Lock

從JDK5.0開始,java提供了更強大的線程同步機制--通過顯示定義同步鎖對象來實現同步。同步鎖使用Lock對象充當。Java.util.concurrent.locks.Lock接口是控制多個線程對共享資源進行訪問的工具。鎖提供了對共享資源的獨占訪問,每次只能有一個線程對Lock對象加鎖,線程開始訪問共享資源之前應先獲得Lock對象。ReentrantLock類實現了Lock,它擁有與synchronized相同的并發性和內存語義,在實現線程安全的控制中,比較常用的是ReentrantLock,可以顯示加鎖,釋放鎖。

同樣的案例:模擬兩個窗口出票
代碼如下:

package Day18.demo3;import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class LockDemo implements Runnable{Lock lock=new ReentrantLock();int num=100;@Overridepublic void run() {while (true){if (num>0){try {print();} catch (InterruptedException e) {e.printStackTrace();}}else {break;}}}public void print() throws InterruptedException {lock.lock();Thread.sleep(100);if (num>0){System.out.println(Thread.currentThread().getName()+num);num--;lock.unlock();}} } package Day18.demo3; public class Test {public static void main(String[] args) {LockDemo lockDemo=new LockDemo();Thread ck1=new Thread(lockDemo,"窗口一");Thread ck2=new Thread(lockDemo,"窗口二");ck1.start();ck2.start();} }


Lock方法只能給代碼塊加同步鎖,不能給方法加,這是與synchronized的區別之一,還有一個區別就是syschronized是隱式的,Lock是顯示的。

線程死鎖

死鎖:

不用的線程分別占用對方需要的同步資源不放棄,都在等對方放棄自己需要的同步資源,于是就形成了線程的死鎖。出現死鎖后,不會出現異常,不會出現提示,所有線程都將處于阻塞狀態,無法繼續下去。例如;一個M國人和一張中國人一起吃飯正常情況為: M國人一刀一叉 中國人:兩根筷子特殊情況為:M國人一刀一根筷子 中國人;一叉一根筷子當遇到特殊情況時,兩人都不放棄對方需要的同步資源,就會一直等待下去,也就是線程死鎖。**設計程序時要考慮清楚鎖的順序,盡量減少嵌套的加鎖交互數量。**

制造一個死鎖:
代碼如下:

package Day18.demo4; public class SiSuo extends Thread {static Object objA = new Object();static Object objB = new Object();boolean flag;public SiSuo(boolean flag) {this.flag = flag;}@Overridepublic void run() {if (flag) {synchronized (objA) {System.out.println("ifOBJA");synchronized (objB) {System.out.println("ifobjB");}}} else {synchronized (objB) {System.out.println("elseOBJA");synchronized (objA) {System.out.println("elseobjA");}}}} } package Day18.demo4; public class Test {public static void main(String[] args) throws InterruptedException {SiSuo si=new SiSuo(true);SiSuo s2=new SiSuo(false);si.start();s2.start();} }

產生死鎖一直等待;

案例:兩個線程交替打印1-100之間的數字
代碼如下:

package Day18.demo5; public class PrintNumDemo extends Thread {static int num = 0;static Object object = new Object();@Overridepublic void run() {while (true) {synchronized (object) {object.notify();//喚醒等待的進程,由于已經有線程持有鎖了,于是不能進入到同步代碼塊try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}if (num < 100) {num++;System.out.println(Thread.currentThread().getName() + ":" + num);} else {break;}try {object.wait();//線程等待,釋放鎖} catch (InterruptedException e) {e.printStackTrace();}}}} } package Day18.demo5; public class Test {public static void main(String[] args) {PrintNumDemo t1=new PrintNumDemo();t1.setName("線程1:");PrintNumDemo t2=new PrintNumDemo();t2.setName("線程2:");t1.setPriority(1);//設置優先級t2.setPriority(10);//將線程2的優先級設置更高,讓線程2優先執行的概率更大t1.start();t2.start();} }

線程通信

線程通訊指的是多個線程通過消息傳遞實現相互牽制,相互調度,即進程間的相互作用。
設計到三個方法:

.wait() 一旦執行此方法,當前線程就進入阻塞狀態,并釋放同步監視器。.notify() 一旦執行此方法,就會喚醒被.wait()阻塞的方法,如果有多個線程被阻塞,就最先喚醒優先級大的哪一個。.notifyAll() 一旦執行此方法,就會喚醒全部被wait()阻塞的進程。## 特別說明:這三個方法必須使用在同步代碼塊或同步方法中這三個方法定義在java.lang.Object類中

經典案例:生產者消費者問題

生產者將產品放在柜臺,而消費者從柜臺處取走產品,生產者一次只能生產固定的數量,產品(例如一個),這時候柜臺中不能再放產品,此時生產者應該停止生產等待消費者拿走產品,此時生產者喚醒消費者來取走產品,消費者拿走產品后,喚醒生產者,消費者開始等待。

代碼如下;

package Day18.demo6; /*柜臺,只有一個 */ public class Countdemo {int num=0;//生產//同步對象是this就是同一個Countdemo對象public synchronized void add(){if (num==0){num++;System.out.println("生產者線程生產了一個產品放在了柜臺上");this.notify();//此時喚醒消費者}else {try {this.wait();//此時已有產品如果此時生產者線程進來了就wait()生產者線程} catch (InterruptedException e) {e.printStackTrace();}}}//消費public synchronized void sub(){if (num==1){num--;System.out.println("消費者線程從柜臺上消費了一個產品");this.notify();//此時喚醒生產者}else {try {this.wait();//此時沒有產品,如果此時消費者進來就外套()消費者線程} catch (InterruptedException e) {e.printStackTrace();}}} } package Day18.demo6; //消費者線程 public class XFZdemo extends Thread{Countdemo countdemo;public XFZdemo(Countdemo countdemo) {this.countdemo=countdemo;}@Overridepublic void run() {while (true){try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}countdemo.sub();}} } package Day18.demo6; //生產者線程 public class SCZdemo extends Thread{Countdemo countdemo;public SCZdemo(Countdemo countdemo) {this.countdemo = countdemo;}@Overridepublic void run() {while (true){try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}countdemo.add();}} } package Day18.demo6; public class Test {public static void main(String[] args) {Countdemo c=new Countdemo();XFZdemo xfz=new XFZdemo(c);SCZdemo scz=new SCZdemo(c);xfz.start();scz.start();} }

新增創建線程的方式

實現Callable接口與使用Runnable相比,Callable功能更加強大一些

相比run()方法,可以有返回值。方法可以拋出異常。支持泛型的返回值。據要借助FutureTask類,獲取返回結果。

接受任務

FutureTask<Integer>futureTask=new FutureTask(任務);創建線程Thread t=new Thread(futureTask);t.start();Integer res=futureTask.get() 獲得線程call方法的返回值

案例:

package Day18.demo7; import java.util.concurrent.Callable; public class CallableDemo implements Callable <Integer>{@Overridepublic Integer call() throws Exception {int num=0;for (int i = 0; i < 11; i++) {num+=i;}return num;} } package Day18.demo7; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; public class Test {public static void main(String[] args) throws ExecutionException, InterruptedException {Callable c=new CallableDemo();FutureTask<Integer> futureTask=new FutureTask<>(c);Thread t=new Thread(futureTask);t.start();Integer res=futureTask.get();System.out.println(res);} }

總結

以上是生活随笔為你收集整理的dya19第十章线程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 女人扒开腿让男人捅爽 | 十八禁视频网站在线观看 | 中文一区在线 | 国产成人亚洲综合 | 中文精品在线观看 | 男生坤坤放进女生坤坤里 | 欧洲最强rapper网站直播 | 成人免费视频国产 | 亲嘴扒胸摸屁股激烈网站 | 一级特级黄色片 | 精品理论片| 欧美日韩在线播放三区四区 | 国内一区二区视频 | 一区二区三区四区亚洲 | 一区二区三区精品视频在线观看 | 亚洲精品久久久久久久蜜桃 | 无码h肉动漫在线观看 | 成人性生交大片免费卡看 | 成 人片 黄 色 大 片 | 人妻熟女aⅴ一区二区三区汇编 | 激情瑟瑟| 一及黄色大片 | a级在线观看视频 | 日本精品在线播放 | 日本一级淫片色费放 | 中文字幕激情视频 | jzzijzzij日本成熟少妇 | 高跟91娇喘 | 草草影院在线 | www五月婷婷| 一区二区三区四区五区av | 日韩欧美xxx | 黄色一级大片在线免费看国产 | 日日爱666 | 国产网站免费在线观看 | 日韩精品一区不卡 | 精品无码一区二区三区蜜臀 | 日本黄色一区 | 成人在线观看免费爱爱 | 中文字幕一区二区在线视频 | 思思久久精品 | 成人作爱视频 | 中文字幕一区二区久久人妻网站 | www奇米影视com | 未满十八岁禁止进入 | 免费精品视频一区二区三区 | 日韩福利电影在线观看 | 色人阁五月天 | av中文字幕一区二区三区 | 日韩视频免费在线观看 | 俺也去综合 | 一区二区三区四区五区视频 | 国产午夜精品无码一区二区 | 精品中文字幕在线观看 | 日本一级淫片免费放 | 欧美做爰全过程免费观看 | www.com操| 国产 欧美 日韩 一区 | 中文字幕在线资源 | 美女扒开下面让男人捅 | 国产高清视频在线免费观看 | 奇米成人影视 | 亚洲天堂久久新 | 亚洲精品视频在线看 | 自拍偷拍国内 | 福利一区三区 | 日本视频黄色 | 你懂得在线| 久久青草免费视频 | 少妇厨房愉情理伦bd在线观看 | 日本理论片 | 182tv福利视频 | 91成人免费在线观看视频 | 欧美日韩国产网站 | 日韩精品一区二区三区在线视频 | 超碰人人cao | 日韩国产在线播放 | 女人脱下裤子让男人桶 | 日本老师巨大bbw丰满 | 青青草国产在线 | a天堂视频在线观看 | 激情伊人| 国产专区在线视频 | www黄色网址| 男女视频免费 | 91毛片视频| 天堂精品在线 | 日韩精品成人一区 | 亚洲av色一区二区三区精品 | 羞羞的网站在线观看 | 女生扒开尿口给男生捅 | 欧美混交群体交 | 制服 丝袜 综合 日韩 欧美 | av在线黄 | 国产强被迫伦姧在线观看无码 | 日韩一二三区在线观看 | a在线播放 | 日本肉体xxxⅹ裸体交 | 日日夜夜91 |