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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

2019-06-03 Java学习日记 day24 多线程

發(fā)布時間:2025/5/22 java 56 豆豆
生活随笔 收集整理的這篇文章主要介紹了 2019-06-03 Java学习日记 day24 多线程 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

多線程

  線程是程序執(zhí)行的一臺路徑,一個進程中可以包含多條線程

  多線程并發(fā)執(zhí)行可以提高程序的效率,可以同時完成多項工作

多線程的應(yīng)用背景

  紅蜘蛛同時共享屏幕給多個電腦

  迅雷開啟多條線程一起下載

  QQ同時和多個人一起視頻

  服務(wù)器同時處理多個客戶端請求

?

多線程并行和并發(fā)

  并行就是兩個任務(wù)同時運行,就是甲任務(wù)進行的同時,乙任務(wù)也在進行(需要多核CPU)

  并發(fā)是指兩個任務(wù)都請求運行,而處理器只能接受一個任務(wù),就把這兩個任務(wù)輪流進行,由于時間間隔較短,使人感覺兩個任務(wù)都在運行

  比如我跟兩個網(wǎng)友聊天,左手操作一個電腦跟甲聊,同時右手用另一臺電腦跟乙聊天,這就叫并行

  如果用一臺電腦我先給甲發(fā)個信息,然后立刻再給乙發(fā)信息,然后再跟甲聊,再跟乙聊。這就叫并發(fā)

?

java程序運行原理和jvm的啟動

  *java命令啟動java虛擬機,啟動jvm,等于啟動了一個應(yīng)用程序,也就是啟動了一個進程,該進程會自動啟動一個 “ 主線程 ”,然后主線程去調(diào)用某個類的 main 方法

?

  *jvm啟動至少啟動了垃圾回收線程和主線程,所以是多線程的

?

多線程程序?qū)崿F(xiàn)

 1. 繼承Thread

    定義類繼承Thread

    重寫run方法

    把新線程要做的是寫在run方法中

    創(chuàng)建線程對象

    開啟新線程,內(nèi)部會自動執(zhí)行run方法

public class demo1_thread {public static void main(String[] args) {mythread mt1 =new mythread(); //創(chuàng)建thread類的子類對象mt1.start(); //開啟線程for(int i=0;i<1000;i++){System.out.println("bbbbb");}}} class mythread extends Thread{ //繼承threadpublic void run(){ //重寫run方法for(int i=0;i<1000;i++){System.out.println("aaaaaaaaaa");}} } 案例

?

 2. 實現(xiàn)runnable

    定義類顯示Runnable接口

    實現(xiàn)run方法

    把新線程要做的事寫在run方法中

    創(chuàng)建自定義的Runnable的子類對象

    創(chuàng)建Thread對象,傳入Runnable

    調(diào)用start()開啟新線程,內(nèi)部會自動調(diào)用Runnable的run方法

public class demo2_Runnnbale {public static void main (String args []){myrunnbale mr =new myrunnbale(); //創(chuàng)建runnable的子類對象new Thread(mr).start(); //將其當做參數(shù)傳遞給thread的構(gòu)造函數(shù),并開啟線程for (int i = 0; i < 1000; i++) {System.out.println("cc");}} } class myrunnbale implements Runnable{@Overridepublic void run() {for (int i = 0; i < 1000; i++) {System.out.println("aaaaaaaaaaaaaa");}}} 案例

實現(xiàn)Runnable的原理

  看Thread類的構(gòu)造函數(shù),傳遞了Runnable接口的引用

  通過init()方法找到傳遞的target給成員變量的target賦值

  查看run方法,發(fā)現(xiàn)run方法中有判斷,如果target不為null就會太哦用Runnable接口子類對象的run方法

?

兩種方式的區(qū)別

  1.繼承Thread:由于子類重寫了Thread類的run(),方太哦用start()時,直接找子類的run()方法

  2.實現(xiàn)Runnable:構(gòu)造函數(shù)中傳入了Runnable的引用,成員變量記住了它,start()調(diào)用run()方法時內(nèi)部成員變量Runnable引用是否為空,不為空編譯時看的siRunnable的run(),運行時執(zhí)行的獅子類的run()方法

?

繼承Thread:

  好處是:可以直接使用Thread類中的方法,代碼簡單

  弊端是:如果已經(jīng)有父類,就不能用這種方法

實現(xiàn)Runnable接口:

  好處是:即使自己定義的縣城類有了父類也沒關(guān)系,因為有了父類也可以實現(xiàn)接口,而且接口是可以多實現(xiàn)的

  弊端是:不能直接使用Thread中的方法需要先獲取到線程對象后,才能得到Thread的方法,代碼復(fù)雜

?

匿名內(nèi)部類實現(xiàn)線程

  1.繼承Thread方法 

  2.實現(xiàn)Runnable方法

public class demo3_Thread {public static void main(String[] args) {new Thread(){ //繼承Thread方法public void run(){ //重寫run方法for (int i = 0; i < 3000; i++) {System.out.println("aaaaaaaaa");}}}.start(); //開啟線程new Thread(new Runnable(){public void run(){for (int i = 0; i < 3000; i++) {System.out.println("bbb");}}}).start();}} 案例

?

獲取名字

  1.通過geyName()方法獲取線程對象的名字

設(shè)置名字

  2.通過構(gòu)造方法函數(shù)可以傳入String類型的名字

?

  通過setName(String)方法可以設(shè)置線程對象的名字

public class demo1_Name {public static void main (String args[]){new Thread("大哥"){public void run(){System.out.println(this.getName()+"aaaaaaaa");}}.start();new Thread(){public void run(){this.setName("戰(zhàn)三");System.out.println(this.getName()+"bb");}}.start();Thread t1= new Thread("大哥"){public void run(){System.out.println(this.getName()+"aaaaaaaa");}};t1.setName("李");t1.start();} } 案例

?

獲取當前線程的對象

  Thread.currentThread(),主線程也可以獲取

public class demo2_currentthread {public static void main(String[] args) {new Thread("毛毛"){public void run (){System.out.println(getName()+"...aaaaaaa");}}.start();new Thread(new Runnable(){public void run(){//Thread.currentThread()獲取當前正在執(zhí)行的線程System.out.println(Thread.currentThread().getName()+"...bb");}}).start();Thread.currentThread().setName("主線程");System.out.println(Thread.currentThread().getName());}} 案例

?

休眠線程

  Thread.sleep(毫秒,納秒),控制當前線程休眠若干毫秒1秒 =1000 * 1000 * 1000納秒? 1000000000

public class demo3_seelp {public static void main(String[] args) throws InterruptedException {//demo1();new Thread(){public void run(){for (int i = 20; i >=0; i--) {try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch block e.printStackTrace();}System.out.println(getName()+"...a");}}}.start();new Thread(){public void run(){for (int i = 20; i >=0; i--) {try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch block e.printStackTrace();}System.out.println(getName()+"..bb");}}}.start();}public static void demo1() throws InterruptedException {for(int i=20;i>=0;i--){Thread.sleep(1000);System.out.println("倒計時"+i+"秒");}}} 案例

?

守護線程

  setDaemon(),設(shè)置一個線程為守護線程,該線程不會單獨執(zhí)行,當其他飛守護線程都執(zhí)行結(jié)束后,自動退出

public class demo4_daemon {public static void main(String[] args) {Thread t1 =new Thread(){public void run(){for (int i = 0; i < 2; i++) {System.out.println(getName()+"..aaaaaaaa");}}};Thread t2 =new Thread(){public void run(){for (int i = 0; i < 50; i++) {System.out.println(getName()+"..bb");}}};t2.setDaemon(true); //當傳入true就是意味著設(shè)置為守護線程 t1.start();t2.start();}} 案例

?

加入線程

  join(),當前線程暫停,等待指定的線程執(zhí)行結(jié)束后,當前線程在繼續(xù)

  join(int),可以等待指定的毫秒之后繼續(xù)

public class demo5_Join {public static void main(String[] args) {final Thread t1 =new Thread(){public void run (){for(int i=0; i<10 ;i++){System.out.println(getName()+"...aaaaaaaaa");}}};Thread t2 =new Thread(){public void run (){for(int i=0; i<10 ;i++){if(i==2){try {t1.join(1);} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(getName()+"...bb");}}};t1.start();t2.start();}} 案例

?

禮讓線程

yield讓出cpu

?

設(shè)置線程的優(yōu)先級

  setPriority() 設(shè)置線程的優(yōu)先級

N1.setPriority(Thread.MIN_PRIORITY);? ? ? ? ? ? //設(shè)置最大的線程優(yōu)先級
N2.setPriority(Thread.MAX_PRIORITY);? ? ? ? ? ?//設(shè)置最小線程優(yōu)先級

?

同步代碼塊

什么情況下需要同步

  當多線程并發(fā),有多段代碼同時執(zhí)行是,我們希望某一段代碼執(zhí)行的過程中cpu不要切換到其他線程工作,這是就需要同步

  如果兩端代碼是同步的,那么同一時間值執(zhí)行一段,在一段代碼每執(zhí)行結(jié)束之前,不會執(zhí)行另一端代碼

同步代碼塊

  使用synchronized關(guān)鍵字加上一個鎖對象來定義一段代碼,這就叫同步代碼塊

  多個同步代碼塊如果使用相同的鎖對象,那么他們就是同步的

public class test_sybchronized {public static void main(String[] args) {final pritner p1=new pritner();new Thread(){public void run(){while(true){p1.print1(); }}}.start();new Thread(){public void run(){while(true){p1.print2(); }}}.start();}} class pritner{ demo d=new demo();public void print1(){synchronized (d) {System.out.println("學習");}}public void print2(){System.out.println("學校");} }class demo{} 案例

?

同步方法

*使用synchronized 關(guān)鍵字修飾一個方法,該方法中所有的代碼都是同步的

public class test2_sybchronized {public static void main(String[] args) {final pritner2 p1=new pritner2();new Thread(){public void run(){while(true){p1.print1(); }}}.start();new Thread(){public void run(){while(true){p1.print2(); }}}.start();}} class pritner2{//非靜態(tài)放入同步方法的鎖對象是this//靜態(tài)的鎖不方法的鎖對象是:該類的字節(jié)碼對象public synchronized void print1(){System.out.print("學");System.out.print("習");System.out.print("的");System.out.print("心");System.out.print("\r\n");}public void print2(){synchronized (this) { System.out.print("學");System.out.print("校");System.out.print("的");System.out.print("路");System.out.print("上");System.out.print("\r\n");}}} 案例

?

線程安全問題

  多線程并發(fā)操作同一數(shù)據(jù)時,就有可能出現(xiàn)線程安全問題

  使用同步技術(shù)可以解決這種問題,把操作數(shù)據(jù)的代碼進行同步,不要多個線程一起操作

public class test2_ticket {public static void main(String[] args) {new ticket().start();new ticket().start();new ticket().start();new ticket().start();}} class ticket extends Thread{private static int ticket =100;public void run(){while(true){synchronized (ticket.class) { if(ticket <=0){break;}try {Thread.sleep(10);} catch (InterruptedException e) {// TODO Auto-generated catch block e.printStackTrace();}System.out.println(getName() + "...這是第" + ticket-- + "號票");}}} } 案例

?

死鎖

多線程同步的時候,如果同步代碼嵌套,使用相同鎖,就有可能出現(xiàn)死鎖

public class test3_ {private static String s1 ="筷子左";private static String s2 ="筷子右";public static void main(String[] args) {new Thread(){public void run (){while(true){synchronized (s1) {System.out.println(getName()+"讀取"+s1+"等待"+s2); synchronized (s2) {System.out.println(getName()+"拿到"+s2+"吃"); }}}}}.start();new Thread(){public void run (){while(true){synchronized (s2) {System.out.println(getName()+"讀取"+s2+"等待"+s1); synchronized (s1) {System.out.println(getName()+"拿到"+s1+"吃"); }}}}}.start();}} 案例

?

轉(zhuǎn)載于:https://www.cnblogs.com/JungTan0113/p/10970951.html

總結(jié)

以上是生活随笔為你收集整理的2019-06-03 Java学习日记 day24 多线程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。