線程學習一:線程基礎

1、什麼是進程、線程、多線程 ?

     操作系統中,進程是分配和調度系統資源的最小單位,而線程是進程中的能獨立執行的最小單元 ;

     一個進程中至少有一個線程,稱爲主線程,主線程還能創建其他線程,所有線程稱爲多線程 ;

     在單核CPU操作系統中,多個線程或者進程採用時間片轉輪的搶佔式方式或取CPU,由於單個時間片很短,給人的感覺就像是多個進程或線程在同時執行,這是僞並行;

     在多核CPU操作系統中,線程或進程數小於CPU數量,那麼足以每個進程或者線程各分配一個CPU同時運行,實現真正的並行 。

2、 JVM 線程與操作系統的線程啥關係 ?

     先理解 線程模型

  • 內核級別線程

    內核級別線程(Kernel-level threading)是指用戶進程通過內核提供API創建的線程。這樣用戶進程裏的線程和內核調度的線程是1:1對應的。這也就最簡單的線程管理方法。

  • 用戶級別線程

     用戶基本線程(User-level threading)是指 用戶進程自己實現線程機制。在這種情況下,內核是不知道有多少線程存在的,同時線程上下文切換更快,而且在不支持多線程的操作系統上也能實現多線程。但是,用戶級別的線程也帶來相當大的壞處,比如不能充分利用多處理器(多核)系統;如果進程中的一個線程執行阻塞的I/O請求,那麼整個用戶進程都會被阻塞。

  • 混合線程

     混合線程是內核級別線程和用戶級別線程的混合體,提供了以上兩種模型的優點,但是帶來很大的複雜性。


     JVM 1.1之前使用的是 用戶級別線程,又稱綠色線程  。

     JVM 1.1之後,由於用戶級別線程的侷限性,之後改爲映射內核級別線程 或者進程 。

     在linux2.6之前,操作系統還沒有線程,當時映射的是進程和微進程,微進程能進行一定的互相通信,進程之間是完全不能互相通信的 。

     linux 2.6 之後,就是目前的,就都是內核級別線程了。


3、java 線程的創建(2種方式)

    閱讀java.lang.Thread類的源碼:

   private Runnable target;
      @Override
      public void run() {
          if (target != null) {
              target.run();
          }
       }
    很明顯,如果我們要創建一個能跑自己邏輯的Thread,就只有2個途徑

    1、爲屬性target賦值一個實現了Runnable對象,該對象實現了自己的run方法 。而這個賦值沒有set方法,只有一個途徑,構造函數(源碼如下)

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

     2、類繼承Thread,並且重寫run方法 。

    示例如下 :

  

/**
 * 線程基礎一:線程的創建
 * @author xubo
 *
 */
public class ThreadStudyOne {

	/**
	 * 通過Thread(Runnable A)進行創建
	 */
	private static Thread getThreadFromRunnable() {
		return new Thread(new Runnable() {
			@Override
			public void run() {
				//what you want to do !
				System.out.println("這是通過Thread(Runnable A)構造函數創建的");
			}

		});
	}

	/**
	 * 繼承
	 */
	public static class myThread extends Thread {
		@Override
		public void run() {
			//what you want to do !
			System.out.println("這是通過重寫父類Thread的run方法創建的");
		}
	}

	private static Thread getThreadFromOverride() {
		return new myThread();
	}

}

4、進程的調度 ,必須使用Thread.start()方法,直接使用run方法是沒有創建線程的  。

 源碼如下

    public synchronized void start() {
        /**
         * This method is not invoked for the main method thread or "system"
         * group threads created/set up by the VM. Any new functionality added
         * to this method in the future may have to also be added to the VM.
         *
         * A zero status value corresponds to state "NEW".
         */
        if (threadStatus != 0)
            throw new IllegalThreadStateException();

        /* Notify the group that this thread is about to be started
         * so that it can be added to the group's list of threads
         * and the group's unstarted count can be decremented. */
        group.add(this);

        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
            }
        }
    }

    private native void start0();

5、Thread常用方法 與 屬性

        a、先級 priority :

     有get與set方法 ,有低中高3個常量,Thread.MIN_PRIORITY=0,Thread.NORM_PRIORITY=5,THREAD.MAX_PRIORITY=10

        b、執行  start() :

     調用操作系統內核API創建一個線程進行執行任務 。

         c、停止  stop() :

     調用瞬間,對應線程拋出ThreadDeathException,導致線程異常終止,會有監視器(鎖對象)未釋放的風險,
目前在JDK中標記爲過時 

          d、打斷  interrupt() :

         調用interrupt()方法,對應線程如果處於sleep睡眠狀態,會直接跑出Interrupted異常,否則對應線程
繼續執行,只是狀態改爲了打斷狀態 。這個方法只能終止睡眠狀態線程,使用時根據需要考慮stop()與interrup()。

             e、睡眠 sleep ():

       sleep(Long m) 表示睡眠多少毫秒 。 如果是sleep(0),表示希望系統直接進行一次CPT資源搶佔分配 ,
給低優先級線程一個運行的機會。該方法不會釋放鎖。

             f、暫停 與 喚醒  wait() ,notify(),notifyAll(),yield() :

        wait(Long m) : 線程阻塞並釋放鎖,直到被notify()或notifyAll喚醒 ,或者等待m毫秒時間。
     wait() : 線程阻塞並釋放鎖,知道被notify()或notifyAll喚醒,否則一直等待
     yield() : 線程阻塞並釋放鎖,知道線程組裏面的其他線程執行完成再執行本線程。 

           g、線程組 ThreadGroup :

      對線程進行了隔離 。 只有同一線程組內的線程才能夠互相調用與阻塞。不自己設置線程組的情況下,
都是繼承創建該線程的線程組。以此向上推,可知,同一個線程源頭創建的線程一般都屬於一個線程組。
是否有權限操作某線程a,可用a.checkAccess()方法。

           h、執行等待 join() :

      join(Thread A) , 強制在A線程執行完後再繼續執行本線程。

           i、守護線程

        與基本線程其實也沒是區別,
        主要特性2點:作用是爲被守護的線程提供監控和服務;會因爲所有被守護的線程的結束而自動結束。  
        調用setDaemon()方法就能設置守護線程了,在守護線程中創建的線程都是守護線程。

 


    

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章