麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學院 > 開發設計 > 正文

Thread線程的方法用法,有代碼例子,簡單易懂

2019-11-14 15:39:53
字體:
來源:轉載
供稿:網友


/**
 *  程序 :
 *      就是指我們寫的保存硬盤當中的靜態文件,叫程序
 *  進程 :  
 *      就是程序被加載進內存,準備或者正在運行時,就叫進程
 *  線程 :
 *      就是程序中不同的執行路徑
 *
 *  線程 :
 *      當我們程序開始執行的時候,就是java中main()方法開始執行,在棧內存中開辟main()棧幀的時候,就是開啟了一個線程
 *      一個線程就是一個棧及其里面的鏈式棧幀,一個棧幀就對應一個方法.
 *  
 */
☆☆☆☆ 重點 ☆☆☆☆ !
    創建一個新的線程有兩種方式,
    但是啟動一個線程,只有一種方式(唯一的一種);
    //三個要點 :
            線程的定義;
            線程的啟動;
            線程開啟之后;
       // 線程的定義 :
                程序不同的執行路徑,從代碼角度來講,線程就是一個類,從內存角度來講,線程就是一個棧和鏈式棧幀
       // 線程必須要先啟動 :
           start();//成員方法
       // 一旦開啟多線程 :
                這個時候,說代碼是從左到右,從上往下執行這句話就不準確了,因為,我們開啟了兩個線程,在每個線程的內部,仍然是從上到下,從左到右,但是線程之間的代碼,沒有固定的先后順序,他們執行的先后順序,是不確定的,和CPU,操作系統,和我們自己的設定,都相關

Thread :    
    //創建線程
    創建一個新的線程,有兩個方式 :
        //第一種 :
                第1步 : 繼承java.lang.Thread;這個類
                第2步 : 重寫run()方法,為什么要重寫?因為run()就相當于新線程的main()方法,就是程序執行的起點和終點;

            //創建了線程,不啟動,不能用 : start();
        //開啟線程 :
            Thread t = new 子類名();
            t.start();//就開啟線程了
Runnable :

        //第二種 :
                第1步 : 實現java.lang.Reunnable接口
                第2步 : 實現接口的run()方法;
        //開啟線程 :
            1 Thread t = new Thread(new 子類名());
               t.start();//開啟線程
            2 Runnable(或者是子類名) r = new 子類名();//多態
              Thread t = new Thread(r);
              t.start();//開啟線程

Thread_start :
        start();//啟動線程(唯一的方法) 默認會去調用該線程的run()方法 成員方法
        啟動一個線程 : 只能是Thread類中的start()方法;

currentThread :
        
        currentThread();//獲取當前線程的內存地址 靜態方法,類名調用就行 對象名也行,底層會默認轉換為類名
        Thread.currentThread();//獲取當前線程的內存地址(在哪個線程寫的,Thread就是哪個線程)

setName :
    
        setName();//給線程取名字,不設置默認是Thread-0,依次累加
        Thread t1 = new 子類名();//默認的名字是在new的時候取得 Thread-0
        t1.setName("t1");//現在,線程名字就改為t1了
        t1.start();
        
getName :
        
        getName();//獲得當前線程的名字  成員方法
        Thread.currentThread().getName();//因為getName()是成員方法,所以想調用這個方法,要先獲得當前線程的內存地址吧,就是Thread.currentThread();

sleep :
    
    sleep : 在那個線程寫的,就鎖定那個線程,和 用哪個線程的引用調用sleep()沒有關系(因為底層也會默認轉成類名)
    //讓某個線程休眠 可以直接類名調用就行了
    //線程中,加了sleep(),就必須拋異常或者捕捉異常
    sleep();//讓當前線程睡眠指定的毫秒數  是靜態方法 類名調用就行
    Thread.sleep(1000);//讓該線程睡眠 1 秒;寫在那個線程,就睡眠那個線程

setPRiority :
    
    setPriority();//設置線程的優先級  成員方法
    線程的默認優先級 :
        //子線程默認繼承父類的線程優先級
        java中線程的優先級有0-10 11個級別
        win當中是1-7 7個優先級
        MIN_PRIORITY : 1  //最低
        MAX_PRIORITY : 10 //最大
        NORM_PRIORITY : 5 //正常

        Thread.currentThread().setPriority(Thread.MIN_PRIORITY);//(設置當前線程的優先級)成員方法要用對象引用去調用吧.先獲取當前線程的內存地址,調用setPriority();去設置優先級 這里設置的為 1 最低的  不設置默認為 5 NORM_PRIORITY
        Thread t = new 子類名();
        t.setPriority(Thread.MAX_PRIORITY);//這和上面那個是一樣的,只不過上面那個,寫在哪,就設置那個線程的優先級,這個是設置指定的那個線程的優先級

//喚醒休眠的兩種方法 :
    
    1 Interrup();//異常喚醒,需要捕捉和拋異常
    2 while();//循環

        Interrup :
            Interrup();//這種方式喚醒,一定要try...catch..處理異常或者是throws拋異常  
            //異常類型 : InterruptedException

            Thread t = new 子類名();//這種是繼承Thread并覆寫run()方法的,這種創建線程方式
            Thread t = new Thread(new 子類名());//這種是實現Runnable接口,并實現run()方法的,這種創建線程方式
            t.start();//啟動線程
            t.interrupt();//強行喚醒(異常喚醒)

        while :
           用while循環(或者別的循環,加if),
           需要強行喚醒,就在主線線程設置 引用(對象名).run=false;就行了
           boolean run = true;//成員變量
           int i =0;//成員變量
           public void run(){//線程類的run()方法
               while(run){//循環 這里如果為true 就會一直循環(死循環把)
                   i++;
        MIN_PRIORITY : 1
                   try{
                       Thread.sleep(1000);
                   }catch(Exception e){
                       e.printStackTrace();
                   }
                   System.out.println( Thread.currentThread().getName()+"--->"+i );
               }
           }

join :
    
    join();//也就是線程的合并,把兩個線程,合并成一個線程(成了單線程)  成員方法
    等著當前線程執行完畢,然后再在本線程后面繼續往下執行,當前行以后,所有的main線程的代碼,都必須等著這個線程執行完畢以后再執行,相當于這個線程和main線程合并,變為單線程程序,又是從上往下執行
        Thread t = new 子類名();
        t.start();//啟動線程
        t.join();//這行一下的main線程的代碼,都必須等待t執行完,才能繼續執行

yield :
    
    yield();//靜態方法 可以直接類名調用,讓當前線程讓位一次(只跟同級)
            1 這是一個靜態方法,一維這:即使用對象調用他,也會在底層轉換為類名調用,停掉的也還是當前所在的線程,也就是說在那個類中調用,就停止那個線程
            2 給同一個優先級的線程讓位,不同的優先級,不讓位
            3 和sleep()方法相同,那個線程調用就停止那和累的線程,但是沒有時間,不固定,只是讓出當前這個時間片,下一個時間片讓不讓,另說

            Thread.yield();//跟同級線程,讓位一次 寫在哪,哪個就讓位一次
        
synchronized: :
    
        synchronized : 并不是往對象里面加鎖,鎖是每個對象都有的屬性,synchronized只是鎖上了這把鎖,是個持續的動作而已
        synchronized 是一個修飾符,修飾的方法,等于是給方法加了一把鑰匙,當一個線程執行這個方法的時候,別的所有線程都不能再去執行這個方法,和用synchronized修飾的方法,一個方法鎖住,所有用synchronized修飾的方法都會鎖上,但是沒有用synchronized修飾的方法,可以訪問//目的就是讓數據同步
        //線程同步本質 :
       當多個線程(服務,任務),操作同一個數據的時候,保證數據一致,本質就是數據同步,是一種數據安全機制
       這種機制,操作上更多是從數據上來保護的
   //異步編程模型 :
       線程是完全獨立的,誰的運行也不會受到別的線程的影響
   //同步編程模型 :
       線程間不是獨立的,互相間有影響的,某些線程必須單獨完成任務以后,才能 夠讓別的線程執行(為什么?)
       
       //同步的原因 :
           1 同步是指數據的同步,為了數據安全,必須要等某個線程對數據操作完成以后,在引入別的線程進行操作
               同步機制,某種程度是多線程編程變成了單線程
           2 同步的環境
               1 必須多線程
               2 多個線程有同時操作同一個數據的可能性
               3 主要就是涉及數據更改的操作
       線程同步是數據的概念
       //方法 : 鎖定,鎖定是一個邏輯上的概念,是為了保證同步的手段
       //方發鎖 : 按照封裝性,根本不可能再是直接就能對數據進行操作只能通過方法進行操作
       //對象鎖 : 堆內存,只要一加鎖,誰也進不來
       //類鎖 : 更大級別的
       只要加了 synchronized 修飾的成員方法(靜態方法),是多個線程不可以用加了synchronized的方法同時訪問這個對象(類)
   同一個方法互斥,不同的方法也互斥

    //靜態方法聲明 :
            又稱為類鎖;
            public synchronized static void m1(){
             System.out.println( "不管誰被鎖,我都會被鎖,他解開,我才解開" );   
            }
            public synchronized static void m2(){
                System.out.println( "不管誰被鎖,我都會被鎖,它解開,我才解開" );
            }
            public static void m3(){
                System.out.println( "別人鎖不鎖,干我何事" );
            }
        比如我有兩個線程,t1和t2把
            t1調用了m1();/*就會鎖住*/ t2就不能調用m1()和m2();/*m2()也會被鎖住*/只能調用m3();//因為m3()沒有用synchronized修飾
    
    //成員方法聲明 :
            又稱對象鎖
            前提是/*對象*/必須是同一個對象
             public synchronized  void m1(){
             System.out.println( "不管誰被鎖,我都會被鎖,他解開,我才解開" );   
            }
            public synchronized  void m2(){
                System.out.println( "不管誰被鎖,我都會被鎖,它解開,我才解開" );
            }
            public  void m3(){
                System.out.println( "別人鎖不鎖,干我何事" );
            }
            比如我有兩個線程,t1和t2把//并且t1線程和t2線程都是同一個對象
            t1調用了m1();/*就會鎖住*/ t2就不能調用m1()和m2();/*m2()也會被鎖住*/只能調用m3();//因為m3()沒有用synchronized修飾

setDaemon :
    
        setDaemon();//設置守護線程(兜底線程)
        只要主線程執行完畢,不管守護線程執行了多少,執行到哪,都不會在執行,也跟著死去,但是跟主線程晚結束一下,
            //活,他先活,死,他先死(要么怎么守護,守護線程,先活,后死)
        Thread t1 = new 子類名();//創建一個線程把,用的是繼承的方式
        t1.setDaemon(true);//里面是布爾型 true/false  把當前線程設置為守護線程
        t1.start();//啟動t1線程把
        //如果我守護線程里面有個死循環(就是不會結束的那種),但是,只要主線程執行完畢,守護線程也會跟著結束

Timer :
    
        1 創建一個定時器(Timer)
        2 創建一個執行定時器任務的類,這個類必須繼承于 TimerTask 這個類,并且,必須覆寫 TimerTask 類中的 run(),方法.(TimerTask)
        3 用 Timer 類里面的 schedule()方法,分配并執行定時器任務(schedule)
    Timer :
        Timer t = new Timer();//創建一個定時器,并且調用Timer類里面的 schedule()方法,分配執行的任務
    
    TimerTask :
        class 類名 extends TimerTask{
            public void run(){
                 System.out.println( new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS").format(new Date()) );//獲取當前時間,輸出
            }
        }
        Date :
            Date d = new Date();//獲取當前的時間
            String d1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS").format(d);//以這種形式,輸出當前時間d

schedule :

    schedule();//Timer里面的schedule(要執行任務的類對象 , 起始的時間 , 任務執行間隔的毫秒數 );//循環執行方法,默認調用run()方法
        t.schedule(
                new 類名(),/*執行定時器任務的類的對象*/
                new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS").parse("2015-09-10 14:48:00 000"),/*其實時間(從什么時間,開始執行)*/
                1000*3)/*執行任務的間隔時間*/;


synchronized :
        //死鎖
        synchronized : 并不是往對象里面加鎖,鎖是每個對象都有的屬性,synchronized只是鎖上了這把鎖,是個持續的動作而已
        死鎖 : 死鎖就是大家都訪問不了的狀態;
            原理 :
                1 兩個線程,兩個對象
                2 先后 嵌套 鎖定 執行 兩個對象(先鎖定第一個對象,再嵌套鎖定第二個對象)
                3 先后 嵌套 鎖定 執行 兩個對象(先鎖定第二個對象,再嵌套鎖定第一個對象)
                4 在第一個線程執行過程中,執行到第二個對象的時候,發現第二個被鎖死了,也只能等待
                5 第二個線程執行過程中,執行到第一個對象的時候,發現第一個被鎖死了,也只能等待

    public class Thread線程{
        public static void main(String[] args){

        //這里我用Object是因為不用再寫實體類了,這個類可以自己寫
        Object o1 = new Object();//第一個對象
        Object o2 = new Object();//第二個對象

        Thread t1 = new Thread(new T1(o1,o2));//第一個線程(調用的是有參構造把)
        Thread t2 = new Thread(new T2(o1,o2));//第二個線程
        t1.start();//啟動線程
        t2.start();//啟動線程

    }
}


class T1 implements Runnable{//線程類吧
    Object o1;//成員變量 這里用于接收實參傳進來的Object的對象引用(實體類用的那個類,這里就要用那個類去接吧)
    Object o2;
    T1(Object o1,Object o2){//有參構造
        this.o1 = o1;//賦值
        this.o2 = o2;
    }
    public void run(){//覆寫的run()方法
        synchronized(o1){//鎖定第一個對象 (o1)
            try{
                Thread.sleep(1000);//不睡眠一秒,有時候不死鎖,睡眠一秒,百分百死鎖(因為如果是我t1線程執行完了,t2線程在開始執行的呢?那就不是死鎖了吧,這樣,t1到這停一秒,一秒足夠t2也走的o2的那個對象那里,所以就死鎖了,都在等待)
            }catch(Exception e){
                e.printStackTrace();
            }
            synchronized(o2){//在鎖定第一個對象(o1)中 嵌套鎖定第二個對象(o2)
                System.out.println( "t1" );//如果,t1執行完成了,就會輸出 但是如果死鎖了,t1就進不來吧 就不會輸出
            }
        }
    }
}
class T2 implements Runnable{//創建線程類
    Object o1;//成員變量 這里用于接收實參傳進來的Object的對象引用(實體類用的那個類,這里就要用那個類去接吧)
    Object o2;
    T2(Object o1, Object o2){//和上面一樣,不懂就看上面的注釋
        this.o1 = o1;
        this.o2 = o2;
}
        public void run(){
            synchronized(o2){//t1線程先鎖定的o1,我這里如果先鎖定o2,沒有關系吧,t1能進o1,但是我也能進o2 ,因為是不同的對象,但是我如果再想進o1,是不是就進不去了(因為t1進去就鎖了)
            try{
                Thread.sleep(1000);//這個也停一秒,就是當t2進來o2這個對象,并鎖定了,t1也肯定就能進去o1這個對象,并也鎖定了,現在就開始進入等待了吧,就是死鎖
            }catch(Exception e){
                e.printStackTrace();
            }
            synchronized(o1){//嵌套鎖定o1
                System.out.println( "t2" );
            }
        }
   }
}

wait :

    wait是 Object 類的方法 ,不是Thread中的方法 Thread中wait也是繼承于 Object

    注意 : 如果該對象沒有被鎖定,則調用wait方法,就會報錯,即只有在同步方法或者同步代碼塊中(也就是某線程訪問,用 synchronized 修飾的方法之后)才可以調用wait方法,notify,notifyAll同理

    this.wait();不是讓當前對象wait,而是讓當前鎖定this對象的線程wait,同時 釋放對this的鎖定

    //wait()和sleep()的區別 :

            wait : wait()會把鎖打開,讓別的線程進來,并且自身進入睡眠,只能等待喚醒,如果不喚醒,會一直休眠(并且,當前線程wait()下面的代碼不會執行,只能等待喚醒,才能執行)

            sleep : sleep()就算設置了休眠,但是鎖也不會打開,別的線程也進不來,并且可以喚醒,但是如果不喚醒,到了指定的睡眠時間,自身也會喚醒(并且,當前線程sleep()下面的代碼不會執行,只能等待喚醒,才能執行)

        this.wait();//如果這個休眠,會打開鎖,讓別的線程執行
        System.out.println( "我在睡眠" );//不會執行,如果沒有線程喚醒,永遠不會執行,會永遠睡眠

        Thread.sleep(5000);//睡眠5秒,并且不會打開鎖,別的線程也得等著,一樣進不來
        System.out.println( "我快喚醒了" );//如果沒有線程喚醒當前睡眠的線程,那么,5秒后,自動醒,一樣會輸出


notify :

        notify是Object 類的方法 ,不是Thread中的方法 Thread中notify也是繼承自Object

        注意 : 如果該對象沒有被鎖定,則調用wait方法,就會報錯,即只有在同步方法或者同步代碼塊中(也就是某線程訪問,用 synchronized 修飾的方法之后)才可以調用wait方法,notify,notifyAll同理

        notify() : 隨機喚醒一個在該對象上睡眠的某一個線程(一般都是誰先睡眠,誰先醒,具體不知道,是系統隨機喚醒的),并且,沒有讓自身進入睡眠狀態
            this.notify();//隨機喚醒一個在該對象上睡眠的線程
            System.out.println( "我能輸出" );//我能輸出,因為上面只是喚醒了一個線程,并沒有讓自身進入睡眠狀態

notifyAll :

        notifyAll是Object 類的方法 ,不是Thread中的方法 Thread中notifyAll也是繼承自Object

        注意 : 如果該對象沒有被鎖定,則調用wait方法,就會報錯,即只有在同步方法或者同步代碼塊中(也就是某線程訪問,用 synchronized 修飾的方法之后)才可以調用wait方法,notify,notifyAll同理

        notifyAll() : 喚醒在該對象上,所有等待的線程,并且,沒有讓自身進入睡眠狀態
            this.notifyAll();//喚醒所有在該對象上睡眠的線程
            System.out.println( "我能輸出" );//我能輸出,因為上面只是喚醒了所有線程,并沒有讓自身進入睡眠狀態


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 日本在线精品视频 | 黄色成人短视频 | 99久久婷婷国产综合精品青牛牛 | av资源在线 | 国产精品亚洲激情 | 3级毛片 | 91午夜免费视频 | 91久久精品一区二区 | 成人免费一区二区三区视频网站 | 成人福利视频在线 | 在线观看一区二区三区四区 | 国产精品成人亚洲一区二区 | 日韩激情一区 | 蜜桃av鲁一鲁一鲁一鲁 | 午夜视频在线观看免费视频 | 成人毛片在线免费看 | 国产亚洲精品综合一区91 | 一本到免费视频 | 欧美日韩国产一区二区三区在线观看 | 一区二区三区欧洲 | 欧美性激情视频 | 国产午夜精品一区二区三区在线观看 | 亚洲欧美国产高清 | 精品国产91久久久久久浪潮蜜月 | 国产精品久久久久无码av | 最近国产中文字幕 | 国产精品一区在线免费观看 | 成年人观看免费视频 | 成人情欲视频在线看免费 | 久久精品小短片 | 中国女警察一级毛片视频 | 精品国产一区二区三区四 | 国产亚洲欧美在线视频 | 亚洲国产中文字幕 | 狠狠ri| 在线a毛片 | 久久免费视频1 | 久久久无码精品亚洲日韩按摩 | 成av在线 | 国产午夜亚洲精品午夜鲁丝片 | 国产精品免费视频观看 |