多線程——線程的建立以及操做線程的相關方法簡介

1、概念:

一、進程:多線程

進程是程序的一次動態執行過程。用進程來對應一個程序,每一個進程對應必定的內存地址空間,而且只能使用它本身的內存空間,各個進程間互不干擾。ide

二、線程:測試

線程是程序內部的控制流,比進程更小的執行單位,是進程內部的子任務。一個進程在執行過程當中,爲了同時完成多個操做,能夠產生多個線程,造成多條執行線索。ui

三、進程與線程的區別:spa

   (1)、每一個進程有一段專有內存空間。進程各自佔有不一樣空間,內存消耗很大,會形成系統在不一樣程序之間切換時開銷很大,進程之間通訊速度很慢.net

   (2)、同一進程的各線程之間共享相同內存空間,利用共享內存來實現數據交換、實時通訊及必要的同步工做。線程之間通訊速度快,相互切換所佔系統資源也小線程

2、建立線程的2種方式

在Java中,線程的建立通常有2種方式:1.繼承Thread類 ;2.實現Runnable接口。對象

方式一:繼承Thread類

示例代碼:blog

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 
package com.model.elgin.thread;

public   class TestThread1 {
   
   
public   static   void main( String [] args) {
         MyThread mt1=
new MyThread();
         MyThread mt2=
new MyThread();
        
//setName方法爲線程命名
         mt1.setName( "mt1" );
         mt2.setName(
"mt2" );;
        
//start方法開啓線程
         mt1.start();
         mt2.start();
    }
        
}
    
class MyThread extends Thread{
    
    @Override
   
public   void run() {
       
for ( int i = 0 ; i < 10 ; i++) {
           
//currentThread()爲Thread類的靜態方法,做用是獲得當前正在運行的線程 
            System.out.println(Thread.currentThread().getName() + ": Hello thread-" + i);
        }
    }   
}

運行結果:繼承

image

從上面的運行結果能夠看出:2個線程在同時運行,爭奪CPU資源,並無前後的優先級,若是再次運行一次,那麼會獲得不一樣的順序結果。

方式二:實現Runnable接口

示例代碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 
package com.model.elgin.thread;

public   class TestThread2 {
   
public   static   void main( String [] args) {
       
//聲明一個資源類實例
        RunThread rt= new RunThread();
       
//將此實例傳入Thread構造方法,建立線程對象
        Thread rmt1= new Thread(rt);
        rmt1.setName(
"rmt1" );
        Thread rmt2=
new Thread(rt);
        rmt2.setName(
"rmt2" );
        rmt1.start();
        rmt2.start();
    }
}

//聲明資源類,須要實現Runnable接口,用來建立線程
class RunThread implements Runnable{
    @Override
   
public   void run() {
       
for ( int i = 0 ; i < 10 ; i++) {
           
//currentThread()爲Thread類的靜態方法,做用是獲得當前正在運行的線程 
            System.out.println(Thread.currentThread().getName() + ": Hello thread-" + i);
        }   
    }
}

注意,這種方式必須將Runnable做爲Thread類的參數,而後經過Thread的start方法來建立一個新線程來執行該子任務。

若是直接調用Runnable的run方法的話,是不會建立新線程的,這跟普通的方法調用沒有任何區別。

事實上,查看Thread類的實現源代碼會發現Thread類是實現了Runnable接口的。

小結:

在Java中是不支持多繼承的,若是一個類已經繼承了另外一個類,那麼它就不能經過繼承Thread類來實現多線程操做,這時候就可使用第二種方式,也就是實現Runable接口來實現。由於Java是單繼承,多實現的。另外一個方面說,若是一個類已經繼承Thread了,那麼它就沒法繼承其餘類去實現更復雜的功能,因此多線程的實現推薦使用實現Runable接口的方式。

三 、Thread類中控制線程的重要方法:

 

#上面2個例子中已使用過

public static native Thread currentThread() 返回當前活動線程的引用;

 

public static native void yield() 使當前執行線程暫時中止執行而讓其餘線程執行;

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
 
package com.model.elgin.thread;

public   class TestThread1 {
   
   
public   static   void main( String [] args)  {
         MyThread mt1=
new MyThread();
         MyThread1 mt2=
new MyThread1();
        
//setName方法爲線程命名
         mt1.setName( "mt1" );
         mt2.setName(
"mt2" );;
        
//start方法開啓線程
         mt1.start(); 
         mt2.start();
    }
        
}
    
class MyThread extends Thread{
    
    @Override
   
public   void run() {
       
for ( int i = 0 ; i < 10 ; i++) {
           
//currentThread()爲Thread類的靜態方法,做用是獲得當前正在運行的線程 
            System.out.println(Thread.currentThread().getName() + ": Hello thread1-" + i);
        }
    }   
}

class MyThread1 extends Thread{
    
    @Override
   
public   void run() {
       
//調用yield方法使當前線程暫停等其它線程執行完畢以後再執行它
        //Thread.yield();
        for ( int i = 0 ; i < 10 ; i++) {
           
//currentThread()爲Thread類的靜態方法,做用是獲得當前正在運行的線程 
            System.out.println(Thread.currentThread().getName() + ": Hello thread2-" + i);
        }
    }   
}

結果對比:

左邊爲未打開34行註釋的結果(即未調用yield方法),右邊是調用yield的結果

imageimage

public static native void sleep(long millis) throws InterruptedException 使當前活動線程睡眠指定的時間millisme;

public static void sleep(long millis,int nanos)throws InterruptedException 使當前活動線程睡眠指定的時間millisme加上十萬分之nanos秒;

public native synchronized void start() 開始運行當前線程;

public void run() 該方法用來定義線程體。一旦線程被啓動執行,就開始執行這個方法;

public final native boolean isAlive() 測試當前線程是否在活動;

 

#---------@Deprecated註解方法開始,不鼓勵使用-----------#

public final void stop() 強制當前線程中止運行,並拋出ThreadDead錯誤;

public void destroy() 撤消當前線程;

public final void suspend() 臨時掛起當前線程;

public final void resume() 恢復運行掛起的線程;

#---------@Deprecated註解方法結束,不鼓勵使用-----------#

 

public final void setPriority(int newPriouity) 設置線程的優先級

能夠在MIN_PRIORITY、NORM_PRIORIITY和MAX_PRIORITY之間,通常MIN_PRIORITY爲1,MAX_PRIORITY爲10;

public final int getPriority() 得到當前線程的優先級;

public final void setName(String name) 設置線程名;

public final String getName() 獲得當前線程名;

public final ThreadGroup getThreadGroup( ) 返回當前的線程組;

小結:

Thread提供的控制線程的主要方法:

  • 啓動和中止:start(), stop()
  • 等待和通知: wait(), notify()
  • 睡眠: sleep()
  • 掛起和恢復: suspend(), resume()
  • 撤消線程:destroy()
  • join()
  • yield()
  • isAlive()
  • setPriority()

後續將結合線程的生命週期來介紹上述的幾個重點方法

相關文章
相關標籤/搜索