什么是JUC以及基本線程的知識


   一:什么是JUC 

  JUC就是java.util.concurrent下面的類包,專門用於多線程的開發。

   二:進程和線程的區別

  進程是可並發執行的程序在某個數據集合上的一次計算活動,也是操作系統進行資源分配和調度的基本單位。

  線程是進程的一個實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位.線程自己基本上不擁有系統資源,只擁有一點在運行中必不可少的資源(如程序計數器,一組寄存器和棧),但是它可與     同屬一個進程的其他的線程共享進程所擁有的全部資源。

  並發:多線程、 多個線程操作一個資源類,快速交替過程。

 

  並行:多核多CPU;

  線程的狀態:(java底層源碼)

    

  public enum State {
        NEW,                  // 新建線程

       RUNNABLE,       // 線程運行

       BLOCKED,          // 線程阻塞

      WAITING, // 等待

      TIMED_WAITING, // 延時等待

      TERMINATED; // 線程銷毀
}

   三:wait和sleep的區別

1:類層面

      wait  ------object

      sleep-------Thread    誰調用誰睡覺

2:是否釋放鎖層面

      wait --------釋放鎖

      sleep--------不釋放鎖

3:使用范圍層面

      wait,notify,notifyall只能在同步方法中或者同步代碼塊中使用

      sleep可以再任意的地方使用

 4:異常

sleep必須捕獲異常

wait不需要捕獲異常

 四:線程的幾種使用方式

1.優先級
 public final void setPriority(int newPriority)
 更改線程的優先級。 
 默認為5,最小為1,最大為10
設置了優先級別之后,級別高 並不是說你一定被優先調度,而是你的被優先調度的概率高而已。
public class Test {
    public static void main(String[] args) {
     
        Tuzi tz=new Tuzi("兔子");
        tz.setPriority(2);
        tz.start();
        
        Wugui wg=new Wugui("烏龜");
        wg.setPriority(8);
        wg.start();
    }
}

public class Wugui extends Thread {
    @Override
    public void run() {
        for (int i = 1; i <=100; i++) {
            System.out.println("我是烏龜我在跑。。"+"----"+this.getName()+"---"+this.getPriority());
        }
    }

    public Wugui(String name) {
        super(name);
    }
    
    
}
2.線程強制運行:join()
可以通過join()方法使得一個線程強制運行,線程強制運行期間,其他線程無法運行,必須等待此線程完成之后,才可以繼續運行。

public final void join() throws InterruptedException
等待該線程終止。 

public final void join(long millis)throws InterruptedException
  等待該線程終止的時間最長為 millis 毫秒。超時為 0 意味着要一直等下去。
package Thread1;
class MyThread implements Runnable{    // 實現Runnable接口
    public void run(){    // 覆寫run()方法
        for(int i=0;i<50;i++){
            System.out.println(Thread.currentThread().getName()
                    + "運行,i = " + i) ;    // 取得當前線程的名字
        }
    }
};
public class demo1{
    public static void main(String args[]){
        MyThread mt = new MyThread() ;    // 實例化Runnable子類對象
        Thread t = new Thread(mt,"線程");        // 實例化Thread對象
        t.start() ;    // 啟動線程
        for(int i=0;i<50;i++){
            if(i>10){
                try{
                    t.join() ;    // 線程強制運行
                }catch(InterruptedException e){}
            }
            System.out.println("Main線程運行 --> " + i) ;
        }
    }
};

3  線程的休眠(sleep)
   在線程中允許一個線程進行暫時的休眠,直接使用Thread.sleep()方法即可。

  sleep定義格式:

public static void sleep(long milis,int nanos)
throws InterruptedException
  首先,static,說明可以由Thread類名稱調用,其次throws表示如果有異常要在調用此方法處處理異常。

所以sleep()方法要有InterruptedException 異常處理,而且sleep()調用方法通常為Thread.sleep(500) ;形式。

 控制當前線程休眠若干毫秒
* 1秒= 1000毫秒
*  1秒 = 1000 * 1000 * 1000納秒 1000000000
package Thread1;
class MyThread implements Runnable{    // 實現Runnable接口
    public void run(){    // 覆寫run()方法
        for(int i=0;i<50;i++){
            try{
                    Thread.sleep(500) ;    // 線程休眠
            }catch(InterruptedException e){}
            System.out.println(Thread.currentThread().getName()
                    + "運行,i = " + i) ;    // 取得當前線程的名字
        }
    }
};
public class demo1{
    public static void main(String args[]){
        MyThread mt = new MyThread() ;    // 實例化Runnable子類對象
        Thread t = new Thread(mt,"線程");        // 實例化Thread對象
        t.start() ;    // 啟動線程
    }
};

4.線程的禮讓(yield)
yield()方法實現線程的禮讓。
package Thread1;
class MyThread implements Runnable{    // 實現Runnable接口
    public void run(){    // 覆寫run()方法
        for(int i=0;i<5;i++){
            try{
                Thread.sleep(500) ;  //休眠一下
            }catch(Exception e){}
            System.out.println(Thread.currentThread().getName()
                    + "運行,i = " + i) ;    // 取得當前線程的名字
            if(i==2){
                System.out.print("線程禮讓:") ;
                Thread.currentThread().yield() ;    // 首先獲取當前線程,然后線程禮讓
            }
        }
    }
};
public class demo1{
    public static void main(String args[]){
        MyThread my = new MyThread() ;    // 實例化MyThread對象
        Thread t1 = new Thread(my,"線程A") ;
        Thread t2 = new Thread(my,"線程B") ;
        t1.start() ;
        t2.start() ;
    }
};

5.判斷線程是否在執行:isAlive
class MyThread implements Runnable{    // 實現Runnable接口
    public void run(){    // 覆寫run()方法
        for(int i=0;i<3;i++){
            System.out.println(Thread.currentThread().getName()
                    + "運行,i = " + i) ;    // 取得當前線程的名字
        }
    }
};
public class ThreadAliveDemo{
    public static void main(String args[]){
        MyThread mt = new MyThread() ;    // 實例化Runnable子類對象
        Thread t = new Thread(mt,"線程");        // 實例化Thread對象
        System.out.println("線程開始執行之前 --> " + t.isAlive()) ;     // 判斷是否啟動
        t.start() ;    // 啟動線程
        System.out.println("線程開始執行之后 --> " + t.isAlive()) ;     // 判斷是否啟動
        for(int i=0;i<3;i++){
            System.out.println(" main運行 --> " + i) ;
        }
        // 以下的輸出結果不確定
        System.out.println("代碼執行之后 --> " + t.isAlive()) ;     // 判斷是否啟動
        
    }
};

6.當前線程:CurrentThread()
  程序可以通過currentThread()方法取得當前正在運行的線程對象,

class MyThread implements Runnable{    // 實現Runnable接口
    public void run(){    // 覆寫run()方法
        for(int i=0;i<3;i++){
            System.out.println(Thread.currentThread().getName()
                    + "運行,i = " + i) ;    // 取得當前線程的名字
        }
    }
};
public class CurrentThreadDemo{
    public static void main(String args[]){
        MyThread mt = new MyThread() ;    // 實例化Runnable子類對象
        new Thread(mt,"線程").start() ;        // 啟動線程
        mt.run() ;    // 直接調用run()方法
    }
};

 

7.線程名稱
  1,在Thread類中可以通過getName()方法取得線程名稱,通過setName()設置線程名稱。

  2,線程的名稱一般在啟動線程前設置,但也允許為運行的線程設置名稱,允許兩個Thread對象有相同名稱,但是應該避免。

  3,如果程序沒有為線程指定名稱,系統會自動為線程設置名稱。

class MyThread implements Runnable{    // 實現Runnable接口
    public void run(){    // 覆寫run()方法
        for(int i=0;i<3;i++){
            System.out.println(Thread.currentThread().getName()
                    + "運行,i = " + i) ;    // 取得當前線程的名字
        }
    }
};
public class ThreadNameDemo{
    public static void main(String args[]){
        MyThread mt = new MyThread() ;    // 實例化Runnable子類對象
        new Thread(mt).start() ;        // 系統自動設置線程名稱
        new Thread(mt,"線程-A").start() ;        // 手工設置線程名稱
        new Thread(mt,"線程-B").start() ;        // 手工設置線程名稱
        new Thread(mt).start() ;        // 系統自動設置線程名稱
        new Thread(mt).start() ;        // 系統自動設置線程名稱
    }
};

五:幾種方法的比較

  1. Thread.sleep(long millis),一定是當前線程調用此方法,當前線程進入阻塞,但不釋放對象鎖,millis后線程自動蘇醒進入可運行狀態。作用:給其它線程執行機會的最佳方式。
  2. Thread.yield(),一定是當前線程調用此方法,當前線程放棄獲取的cpu時間片,由運行狀態變會可運行狀態,讓OS再次選擇線程。作用:讓相同優先級的線程輪流執行,但並不保證一定會輪流執行。實際中無法保證yield()達到讓步目的,因為讓步的線程還有可能被線程調度程序再次選中。Thread.yield()不會導致阻塞。
  3. t.join()/t.join(long millis),當前線程里調用其它線程1的join方法,當前線程阻塞,但不釋放對象鎖,直到線程1執行完畢或者millis時間到,當前線程進入可運行狀態。
  4. obj.wait(),當前線程調用對象的wait()方法,當前線程釋放對象鎖,進入等待隊列。依靠notify()/notifyAll()喚醒或者wait(long timeout)timeout時間到自動喚醒。
  5. obj.notify()喚醒在此對象監視器上等待的單個線程,選擇是任意性的。notifyAll()喚醒在此對象監視器上等待的所有線程。

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM