JAVA中執行緒的建立

蝴蝶飛啊飛發表於2019-11-06

一、執行緒(Thread)

1. 執行緒

執行緒:是指程式中的順序流

多執行緒:一個程式中的多個順序流同時執行

(1) 執行緒的狀態:

新生

就緒

執行

阻塞

終止

(2) 學習多執行緒:

1) 執行緒的建立

2) 執行緒的狀態

3) 執行緒的安全

4) 執行緒的通訊

2. 執行緒的建立

1) 繼承 Thread ,重寫 run() 方法

(1) run() 方法中定義執行緒體

(2) 開啟:使用 start() 方法開啟執行緒

// 繼承 Tread

public class Thread01 extends Thread{

// 重寫 run() 方法

// 多執行緒的執行緒體

@Override

public void run() {

for(int i=1;i<=20;i++){

System.out.println(" 一邊敲程式碼 ...");

}

}

public static void main(String[] args) {

// 開啟多執行緒 建立執行緒

Thread01 th=new Thread01();

// 開啟執行緒

th.start();

//th.run();    注意 : 這是方法的呼叫 , 不是多執行緒的開啟

for(int i=1;i<=20;i++){

System.out.println(" 一邊聊天 ...");

}

}

}

2) 實現 Runnable 介面,重寫 run() 方法(推薦使用,執行緒安全)

開啟:通過外匯返傭http://www.kaifx.cn/Tread 類中的 start() 方法開啟執行緒

優點: (1) 避免了單繼承的侷限性

(2) 實現資源的共享

public class Thread02 implements Runnable{

// 定義執行緒體的方法 , 當被呼叫的時候 , 會逐行執行裡面的程式碼

@Override

public void run() {

for(int i=1;i<=100;i++){

System.out.println(" 一邊敲程式碼 ...");

}

}

public static void main(String[] args) {

Thread02 th=new Thread02();

// 開啟執行緒 // 建立執行緒

Thread t=new Thread(th);  // 因為開啟執行緒的方法在 Thread 類中 ,Thread 做為代理類出現

t.start();

for(int i=1;i<=100;i++){

System.out.println(" 一邊聊天 ...");

}

}

}

實現資源共享:

/*

 * 模擬鐵路 12306

 * 需求: 100 張票 ,3 個人買完

 * 資源共享: 100 張票

 */

public class Thread03 implements Runnable{

// 成員 資源

int tikets=100;

@Override

public synchronized void run() {

// 迴圈買票

while(true){

if(tikets<=0){

break;

}

// 捕捉異常

//static void   sleep(long millis) 在指定的毫秒數內讓當前正在執行的執行緒休眠(暫停執行),此操作受到系統計時器和排程程式精度和準確性的影響

try {

Thread.sleep(100);  // 執行緒睡眠 100ms

} catch (InterruptedException e) {

e.printStackTrace();

}

//static Thread    currentThread() 返回對當前正在執行的執行緒物件的引用

//String     getName() 返回該執行緒的名稱

System.out.println(Thread.currentThread().getName()+" 正在購買第 "+tikets--);

}

}

public static void main(String[] args) {

Thread03 th=new Thread03 ();

// 開啟三個執行緒

Thread th1=new Thread(th," 張三 ");

Thread th2=new Thread(th," 李四 ");

Thread th3=new Thread(th," 王五 ");

th1.start();

th2.start();

th3.start();

}

}

3) 實現 Callable 介面,重寫 call() 方法,方法中定義執行緒體(瞭解)

優點:可以丟擲異常,可以有返回值

// 導包

import java.util.concurrent.Callable;

import java.util.concurrent.ExecutionException;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

import java.util.concurrent.Future;

// 實現 Callable 介面   <> 可以新增泛型,引用型別的資料

public class Race05 implements Callable<Integer>{

// 儲存贏的人的名字

String winner=null;

// 重寫 call() 方法,方法中定義執行緒體

@Override

public Integer call() throws Exception {

// 開始遊戲 , 迴圈停止遊戲結束

for(int i=1;i<=100;i++){

if(" 兔子 ".equals(Thread.currentThread().getName()) && i%10==0){

try {

Thread.sleep(2);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

System.out.println(Thread.currentThread().getName()+" 正在跑第 "+i+" ");

// 呼叫有 Boolean 型別返回值的結束方法

boolean flag=over(i);

// 判斷返回值是 true ,或為 false

if(flag){

return i;

}

}

return -1;

}

/**

 * @param steps   當前執行緒的步數

 * 返回值 : 如果有人贏了返回 true, 否則返回 false

 */

public boolean over(int steps){

if(winner!=null){

return true;

}else{

if(steps==100){

winner=Thread.currentThread().getName();

return true;

}

return false;

}

}

public static void main(String[] args) throws InterruptedException, ExecutionException {

Race05 race=new Race05();

//1. 建立執行服務

ExecutorService server=Executors.newFixedThreadPool(2);

//2. 提交執行

Future result1=server.submit(race);

Future result2=server.submit(race);

//3. 獲取結果

Integer i1=(Integer) result1.get();

Integer i2=(Integer) result2.get();

System.out.println(i1+"---->"+i2);

//4. 關閉服務

server.shutdown();

}

}

2. 執行緒狀態問題

1) 狀態:

新生狀態: new

就緒狀態: start() 執行緒就會進入到就緒狀態 , 執行緒會進入到就緒佇列 , 等待 CPU 的排程

執行狀態:

阻塞狀態: 非常執行完畢 , 通過程式進行控制

終止狀態:

注意: 一個執行緒一旦進入到終止狀態 , 沒有辦法恢復了 , 就算是重寫 new 一個執行緒 , 也不剛那個執行緒了,一個執行緒一旦進入到阻塞狀態 , 無法直接恢復到執行 , 等待阻塞接觸之後恢復到就緒狀態

2) 如何進入到就緒狀態

1 start()

2 )阻塞解除

3 )執行緒切換,被切換的執行緒進入到就緒狀態

4 yield() 禮讓執行緒

3) 如何進入到阻塞狀態

1 sleep() 方法

2 join()

3 wait()

4) 如何讓一個執行緒進入到終止狀態

1 )正常執行完畢

2 destroy() |stop() 已過時

3 )通過標識手動判斷

3.Thread 類的方法學習

1 sleep() 執行緒休眠

1. 模擬網路延遲

2. 放大問題的可能性

注意:sleep() 執行緒的休眠是抱著資源不放進行休眠,同步的是物件資源,讓出的是 CPU 的資源

// 實現 Runnable 介面

public class State01 implements Runnable{

public static void main(String[] args) {

 new Thread(new State01()).start();

}

/*

 * 倒數計時   10 9 8 7 6 5 4 3 2 1

 * 重寫 run() 方法

 */

@Override

public void run() {

for(int i=10;i>=0;i--){

// 模擬網路延遲

try {

Thread.sleep(1000);   //sleep() 執行緒的休眠 1000ms=1s

} catch (InterruptedException e) {

e.printStackTrace();

}

if(i==0){

System.out.println(" 過年好 ...");

break;

}

System.out.println(i);

}

}

}

2 yield() 禮讓執行緒

static Thread   currentThread()  

返回對當前正在執行的執行緒物件的引用

String   getName()  

返回該執行緒的名稱

//static void     yield() 暫停當前正在執行的執行緒物件,並執行其他執行緒

public class Yield03 implements Runnable{

public static void main(String[] args) {

new Thread(new Yield03(),"A").start();

new Thread(new Yield03(),"B").start();

}

@Override

public void run() {

System.out.println(Thread.currentThread().getName()+"start...");

//yield() 禮讓執行緒,等待 CPU 的再度呼叫,但是是隨機分配

Thread.yield();  // 靜態方法

System.out.println(Thread.currentThread().getName()+"end...");

}

}

3 getState() 方法

Thread.State  getState()

  返回該執行緒的狀態

void  setPriority(int newPriority)

更改執行緒的優先順序

/*

 * getState() 方法

 * 執行緒的優先順序: 提高優先執行的可能性 , 但是不一定就會先執行

 * void setPriority(int newPriority) 更改執行緒的優先順序。

 * 優先順序分為1~10 1 最小   10 最大

 * Thread.NORM_PRIORITY 5 ( 預設為 5)

 * Thread.MAX_PRIORITY  10

 * Thread.MIN_PRIORITY  1

 */

public class GetState04 {

public static void main(String[] args) {

Thread th=new Thread(()->{

for(int i=1;i<=10;i++){

try {

Thread.sleep(100);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(" 一邊學習 ...");

}

});

th.setPriority(Thread.NORM_PRIORITY);

System.out.println(th.getPriority());

System.out.println(th.getState());//NEW

th.start();

System.out.println(th.getState());//RUNNABLE

for(int i=1;i<=10;i++){

if(i==5){

try {

Thread.sleep(500);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

System.out.println(th.getState());

}

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

System.out.println(th.getState());

if(th.getState()== Thread.State.TERMINATED){

System.out.println(" 終止 ");

}

}

}

4 join() 合併執行緒,插隊執行緒

void join()

       等待該執行緒終止。

 void join(long millis)

       等待該執行緒終止的時間最長為 millis 毫秒。

void join(long millis, int nanos)

       等待該執行緒終止的時間最長為 millis 毫秒 + nanos 納秒

/*

 * join() 合併執行緒 , 插隊執行緒

模擬:父親讓兒子去買菸的過程

 */

public class JoinDemo05 {

public static void main(String[] args) {

new Thread(new Father()).start();

}

}

class Father implements Runnable{

@Override

public void run() {

System.out.println(" 想抽菸 ...");

System.out.println(" 給兒子錢,讓兒子去買菸 ..");

Thread th=new Thread(new Son());

th.start();

try {

th.join();// 合併執行緒

} catch (InterruptedException e) {

e.printStackTrace();

System.out.println(" 兒子丟了 , 趕緊去找兒子 ..");

}

System.out.println(" 接過煙 , 吸一口 , ~");

}

}

class Son  implements Runnable{

@Override

public void run() {

System.out.println(" 接過前 , 給老爸去買菸 ...");

System.out.println(" 路邊有個電玩城 , 進去玩 10s...");

for(int i=1;i<=10;i++){

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(i+"s...");

}

System.out.println(" 趕緊去買菸 ...");

System.out.println(" 把煙給老爸 , 前揣兜裡 ...");

}

}

4. 執行緒安全

多個執行緒同時操作同一個資源的時候, 才可能會出現執行緒安全問題

1 synchronized 關鍵字

通過同步synchronized 關鍵字控制執行緒安全 :

同步方法

靜態方法

成員方法

同步塊 synchronized ( |this| 資源 ){ 程式碼 }

: 類名 .class 一個類的 Class 物件 一個類只有一個 Class 物件

// 通過同步 synchronized 關鍵字控制執行緒安全

public class Single01 {

public void main(String[] args) {

new Thread(()->{System.out.println(Single.newInstance());}).start();;

new Thread(()->{System.out.println(Single.newInstance());}).start();;

}

}

class Single{

//2. 私有的靜態的該類的引用

private static Single single=null;

//1. 構造器私有話

private Single(){}

//3. 公共的靜態的方法

// 在方法上新增鎖 , 鎖方法

/*public static synchronized Single newInstance(){

if(single==null){

single=new Single();

}

return single;

}*/

// 同步塊

/*public static Single newInstance(){

synchronized (Single.class) {  // 控制多執行緒排隊執行

if(single==null){

single=new Single();

}

}  //{} 中的程式碼就是排隊執行的程式碼

return single;

}*/

public static Single newInstance(){

if(single==null){

//A B C

synchronized (Single.class) {  // 控制多執行緒排隊執行

// 雙重檢查 double check

if(single==null){

single=new Single();

}

}  //{} 中的程式碼就是排隊執行的程式碼

}

return single;

}

}


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69946279/viewspace-2662888/,如需轉載,請註明出處,否則將追究法律責任。

相關文章