1. 程式人生 > >一、多執行緒基礎概念、實現執行緒三種方法、中斷執行緒方法,以及執行緒狀態轉化

一、多執行緒基礎概念、實現執行緒三種方法、中斷執行緒方法,以及執行緒狀態轉化

1、CPU核心數和執行緒數的關係

1:1的關係,引入超執行緒之後,就是1:2

2、cpu時間輪轉機制,即RR排程

3、程序和執行緒

程序:程式執行資源分配最小單位,程序內部有多個執行緒,多個執行緒之間會共享程序資源

執行緒:CPU排程的最小單位

4、並行和併發

並行:同一時刻可以處理的事情

併發:同一時間段可以處理的事情

5、高併發程式設計的意義、好處和注意事項

1、可以充分利用CPU的資源

2、加快響應使用者的時間

共享資源,就能存在衝突;

如果多執行緒控制不好,可能會存在死鎖;

執行緒太多,搞垮機器,或記憶體溢位;

java當中的執行緒,一個簡單的main函式至少執行五個執行緒

public class OnlyMain {     public static void main(String[] args) {         //虛擬機器執行緒管理的介面         ThreadMXBean bean = ManagementFactory.getThreadMXBean();         ThreadInfo[] dumpAllThreads = bean.dumpAllThreads(false, false);         for(ThreadInfo temp : dumpAllThreads) {             System.out.println("[id:"+temp.getThreadId()+"]"+"  name:"+temp.getThreadName());         }     } }

得到的結果如下

[id:5]  name:Attach Listener [id:4]  name:Signal Dispatcher [id:3]  name:Finalizer                //釋放記憶體的,虛擬機器不保證一定會執行 [id:2]  name:Reference Handler [id:1]  name:main

java中啟動執行緒的方式:

1、繼承Thread

2、實現Runnable介面

3、介面Callable

如下是三種方法的簡單實用例項:

public class TestThread {     private static class FirstThread extends Thread{         public void run() {             {                 System.out.println("thread");             }         }     }     private static class runThread implements Runnable{         @Override         public void run() {             System.out.println("run");         }     }     private static class CallThread implements Callable<String>{         @Override         public String call() throws Exception {             return "call";         }     }     public static void main(String[] args) throws InterruptedException, ExecutionException {         new Thread(new FirstThread()).start();         new Thread(new runThread()).start();                  CallThread callThread = new CallThread();         //FutureTask實現了Runnable介面的,所以這樣封裝之後就可以使用         FutureTask<String> futureTask = new FutureTask<>(callThread);         new Thread(futureTask).start();

        //獲取callable返回的值,同時這裡的get方法是阻塞的        System.out.println(futureTask.get());     } }

讓執行緒停止工作的方法:

1、自然執行完;

2、丟擲異常;

3、stop():結束執行緒的時候,無法保證資源是釋放的,已經被廢棄;

4、resume():無法保證資源是釋放的,已經被廢棄;

5、suspend():掛起,呼叫之後執行緒不會釋放資源的,可能會導致死鎖等問題;已經廢棄;

現在使用以下方法:

6、interrupt() :中斷一個執行緒,並不是強行關閉,而是打個招呼,是否中斷由執行緒自己決定,中斷標誌位=true

7、 isInterrupted():判斷當前執行緒是否處於中斷狀態

8static方法interrupted():判斷單籤執行緒是否處於中斷狀態,和7不同的是,他會修改中斷標誌位=false

Thread:

public class EndThread {     private static class UseThread extends Thread {         public UseThread(String name) {             super(name);         }         @Override         public void run() {             String currentName = Thread.currentThread()                     .getName();             while (!isInterrupted()) {                 System.out.println(currentName + " is running!");             }             System.out.println(currentName + " is stoped!");         }     }     public static void main(String[] args) throws InterruptedException {         Thread thread = new UseThread("endThread");         thread.start();         Thread.sleep(10);         thread.interrupt();     } }

執行結果:

endThread is running! endThread is running! endThread is running! endThread is running! endThread is running! endThread is running! endThread is running! endThread is running! endThread is running! endThread is running! endThread is running! endThread is running! endThread is running! endThread is running! endThread is running! endThread is running! endThread is running! endThread is stoped!

Runnable:

public class EndRunnable {

    private static class UseRunnable implements Runnable {         @Override         public void run() {             String currentName = Thread.currentThread().getName();             while (!Thread.currentThread().isInterrupted()) {                 System.out.println(currentName + " is running!");             }             System.out.println(currentName + " is stoped!");         }     }     public static void main(String[] args) throws InterruptedException {         UseRunnable useRunnable = new UseRunnable();         Thread thread = new Thread(useRunnable,"endThread");         thread.start();         Thread.sleep(10);         thread.interrupt();     } }

執行結果:

endThread is running! endThread is running! endThread is running! endThread is running! endThread is running! endThread is running! endThread is running! endThread is running! endThread is running! endThread is running! endThread is running! endThread is running! endThread is running! endThread is running! endThread is running! endThread is running! endThread is running! endThread is stoped!

callable:

丟擲InterruptedException異常的處理:

public class EndRunnable {

    private static class UseRunnable implements Runnable {         @Override         public void run() {             String currentName = Thread.currentThread().getName();             while (!Thread.currentThread().isInterrupted()) {                 try {                     Thread.sleep(100);                 } catch (InterruptedException e) {                     e.printStackTrace();                 }                System.out.println(currentName + "-"+Thread.currentThread().isInterrupted());             }             System.out.println(currentName + " is stoped!--"+Thread.currentThread().isInterrupted());         }     }     public static void main(String[] args) throws InterruptedException {         UseRunnable useRunnable = new UseRunnable();         Thread thread = new Thread(useRunnable,"endThread");         thread.start();         Thread.sleep(10);         thread.interrupt();     } }

方法裡如果丟擲InterruptedException,執行緒的中斷標誌位會被複位成false,如果確實是需要中斷執行緒,要求我們自己在catch語句塊裡再次呼叫interrupt()。

執行結果:

java.lang.InterruptedException: sleep interrupted     at java.lang.Thread.sleep(Native Method)     at multcurrent.EndRunnable$UseRunnable.run(EndRunnable.java:25)     at java.lang.Thread.run(Unknown Source) endThread-false endThread-false endThread-false endThread-false endThread-false

。。。

中斷執行緒的使用誤區

有些人在中斷執行緒的時候,不使用isInterrupted判斷執行緒是否中斷,而是自己定義一個布林變數來判斷,如下:

    private static class UseRunnable implements Runnable {         private volatile boolean cancel = false;                  public void cancel() {             cancel = true;         }         @Override         public void run() {             while (cancel) {             }         }     }

這個時候,如果執行緒當中的程式碼發生了阻塞,cancel的變化會改變的不及時,可能帶來未知的問題;此時可以將while(true)改為while(true || isInterrupted),才是最為保險的!

執行緒的狀態轉換: