嗨~! 線程 —— 持續(xù)更新(^-^)V

進(jìn)階線程啦~.png

進(jìn)程

是了解線程之前的首要概念,當(dāng)我們想要在系統(tǒng)中運(yùn)行程序,首先需要向操作系統(tǒng)申請資源(內(nèi)存、文件句柄),申請資源在操作系統(tǒng)中的基本單位是進(jìn)程。一個進(jìn)程可以包含多個線程,同一個進(jìn)程中的線程共享該進(jìn)程中的資源,如內(nèi)存空間、文件句柄等

HelloThread

線程創(chuàng)建、啟動、運(yùn)行
新建線程 new
啟動線程 start
運(yùn)行線程 run -- 運(yùn)行一個線程就是讓JVM執(zhí)行該線程的 run 方法

  public class HelloThread {
    public static void main(String[] args) {
      Thread thread = new Thread();
      Thread childThread = new ChildThread();
      Thread childThred2 = new Thread(new ChildThread());
      Thread student = new Thread(new StudentRunnable());
      System.out.println("----------- Test thread's name in Called Method -----------");
      threadName();
      
      System.out.println("----------- Test 1. new Thread() 2.setName(\"HelloWorld\") -----------");
      thread.setName("HelloWorld");
      thread.start();
      System.out.println("Thread: " + thread.getName() + " starting");
      
      System.out.println("----------- Test ChildThread -----------");
      childThread.start();
      System.out.println("ChildThread: " + childThread.getName() + " starting...");
      childThred2.start();
      // 線程是“一次性用品”
      // 多次調(diào)用同一 thread 的 start 會出現(xiàn) IllegalThreadStateException
      // 因為threadStatus != 0 0為線程初始狀態(tài)
      // childThred2.start();
      System.out.println("ChildThread: " + childThred2.getName() + " starting...");
      System.out.println("----------- Test Student of Runnable -----------");
      student.start();
      System.out.println("StudentThread: " + student.getName() + " starting...");
    }
    
    public static void threadName() {
      System.out.println("The thread name of main called method's currentThread is " + Thread
        .currentThread().getName());
    }
    
  }

  class ChildThread extends Thread {
    @Override
    public void run() {
      // 執(zhí)行run的順序是不一定的
      // run執(zhí)行完畢,線程即結(jié)束
      // 結(jié)束后,所占用的資源包括內(nèi)存都將被JVM回收
      System.out.println(Thread.currentThread().getName() + " running...");
    }
  }

  class StudentRunnable implements Runnable {
    
    @Override
    public void run() {
      System.out.println(Thread.currentThread().getName() + " running...");
    }
  }

Console Output:

  ----------- Test thread's name in Called Method -----------
  The thread name of main called method's currentThread is main
  ----------- Test 1. new Thread() 2.setName("HelloWorld") -----------
  Thread: HelloWorld starting
  ----------- Test ChildThread -----------
  ChildThread: Thread-1 starting...
  ChildThread: Thread-3 starting...
  ----------- Test Student of Runnable -----------
  ----------- Test run of ChildThread -----------
  Thread-3 running...
  ----------- Test run of ChildThread -----------
  Thread-1 running...
  Thread-4 running...
  StudentThread: Thread-4 starting...
  • Thread的創(chuàng)建默認(rèn)下標(biāo)從0開始,如源碼示 threadInitNumber for 匿名線程自增長編號。threadInitNumber 初始為0
    /* For autonumbering anonymous threads. */
    private static int threadInitNumber;
    private static synchronized int nextThreadNum() {
        return threadInitNumber++;
    }

    public Thread() {
        init(null, null, "Thread-" + nextThreadNum(), 0);
    }

創(chuàng)建線程綜述:

    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }

基于Thread的run實現(xiàn)(實現(xiàn)Runnable的run),創(chuàng)建線程有兩種方式:
1. 基于繼承(Inheritance)。實現(xiàn) Thread 中的 run 方法
2. 基于組合(Composition)。new Thread(Ruannable instance) 通過 Runnable 的實例,執(zhí)行實例中的 run。實用組合更好的降低耦合

public class ThreadCreation {
  private static final String PREFIX = "prefix";
  
  public static void main(String[] args) {
    // ---------- 獲取處理器個數(shù) ----------
    final int processorNum = Runtime.getRuntime().availableProcessors();
    
    // ---------- 創(chuàng)建線程方式 ----------
    // ---------- 創(chuàng)建線程.Way1 基于繼承 ----------
    ChildrenOfRunnable runnableTask = new ChildrenOfRunnable();
    IntStream.range(0, 2 * processorNum).mapToObj(index -> new Thread(runnableTask)).forEach(
      Thread::start);

    // ---------- 創(chuàng)建線程.Way2 基于組合 ----------
    Thread thread = new ChildrenOfThread();
    thread.start();
  }
    @Override
    public void run() {
      System.out.println("childrenOfThread is running.");
    }
  }
  
  static class ChildrenOfRunnable implements Runnable {
    private int index = 0;
    
    @Override
    public void run() {
  
  static class ChildrenOfThread extends Thread {
      System.out.println("childrenOfRunnable " + index++ + " is running.");
    }
  }
}

線程核心屬性

  • id同一個JVM實例中不會存在重復(fù)的線程id,默認(rèn)從0開始自增
  • name 主要便于開發(fā)人員查看,是可以重復(fù)的
  • daemon是否要設(shè)置為守護(hù)線程,默認(rèn)同父線程daemon性質(zhì)一致。守護(hù)線程一般執(zhí)行一些重要性不是很高的任務(wù),比如監(jiān)聽其他線程的運(yùn)行情況
  • priority線程優(yōu)先級,默認(rèn)同父線程priority值一致,1≤n≤線程組priority≤10。優(yōu)先級并一定保證線程會按照優(yōu)先級的順序執(zhí)行,只是給到調(diào)度器一個提示信息。
public final static int MIN_PRIORITY = 1;
public final static int NORM_PRIORITY = 5;
public final static int MAX_PRIORITY = 10;

線程屬性設(shè)置主要在Thread.init

    private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc) {
        if (name == null) {
            throw new NullPointerException("name cannot be null");
        }

        this.name = name.toCharArray();

        Thread parent = currentThread();
        SecurityManager security = System.getSecurityManager();
        if (g == null) {
            /* Determine if it's an applet or not */

            /* If there is a security manager, ask the security manager what to do. */
            if (security != null) {
                g = security.getThreadGroup();
            }

            /* If the security doesn't have a strong opinion of the matter use the parent thread group. */
            if (g == null) {
                g = parent.getThreadGroup();
            }
        }

        /* checkAccess regardless of whether or not threadgroup is explicitly passed in. */
        g.checkAccess();

        /* Do we have the required permissions? */
        if (security != null) {
            if (isCCLOverridden(getClass())) {
                security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
            }
        }

        g.addUnstarted();

        this.group = g;
        this.daemon = parent.isDaemon();
        this.priority = parent.getPriority();
        if (security == null || isCCLOverridden(parent.getClass()))
            this.contextClassLoader = parent.getContextClassLoader();
        else
            this.contextClassLoader = parent.contextClassLoader;
        this.inheritedAccessControlContext =
                acc != null ? acc : AccessController.getContext();
        this.target = target;
        setPriority(priority);
        if (parent.inheritableThreadLocals != null)
            this.inheritableThreadLocals =
                ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
        /* Stash the specified stack size in case the VM cares */
        this.stackSize = stackSize;

        /* Set thread ID */
        tid = nextThreadID();
    }

線程常用方法

  • synchronized void start() 啟動線程。一個線程被start多次會拋出- IllegalThreadStateException異常
  • void run()實現(xiàn)線程的任務(wù)處理邏輯。一般,程序不應(yīng)該直接調(diào)用該方法,由JVM調(diào)用
  • final synchronized void join()等待相應(yīng)線程運(yùn)行結(jié)束。T_A調(diào)用T_Bjoin(),T_A將會等待T_B執(zhí)行結(jié)束再執(zhí)行
  • static void yield()主動放棄對當(dāng)前時間片的占用,但是方法的執(zhí)行并不可靠。若T_A調(diào)用yield方法:
    • 當(dāng)前資源空閑,調(diào)度器會忽略這個提示,T_A繼續(xù)執(zhí)行
    • 當(dāng)前資源忙,T_A主動放棄當(dāng)前時間片,調(diào)度器收到提示切換上下文,T_A掛起
  • static void sleep() 一定會執(zhí)行,掛起一定時間
  • static Thread currentThread()返回執(zhí)行當(dāng)前代碼的線程
  • void interrupt()主動打斷線程阻塞狀態(tài)
  • boolean isInterrupted() 執(zhí)行isInterrupted(false) 返回 if this thread has been interrupted; 即線程是否被打斷過
  • static boolean interrupted() 實際上執(zhí)行currentThread().isInterrupted(true); 即返回當(dāng)前線程的interrupted并復(fù)位interrupted狀態(tài)
  • native boolean isInterrupted(boolean ClearInterrupted)線程是否被打斷,同時是否復(fù)位interrupted標(biāo)識
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容