Java個人對線程和進程的理解及面試相關

進程: 操作系統運行程序時分配資源的最小單位,進程和進程之間是相互獨立的

線程: cpu調度的最小單位,它必須依賴於進程.線程在運行時會佔用該進程的部分資源,線程之間是可以共享該進程所擁有的全部資源.但是線程與線程之間也有自己的獨立空間,稱之爲線程私有空間.

講到線程,一個進程有多個線程,所以會有多線程併發問題出現.

什麼是併發: 併發就好比一條高速收費口(這就相當於一個進程),假如這個入口有8個收費口,就代表着這個進程開了8個線程一直在跑. 這時併發好比在一個小時一共有多少汽車通過了這個收費口.這就是併發量, 這個併發控制不好就會出現排長隊現象,也就是影響性能.

在操作多線程中需要考慮以下事項

1:線程和線程之間的安全性

因爲一個進程中多線程是資源共享的,也就是都可以訪問同一內存地址當中的一個變量.

若每個線程中對全局變量、靜態變量只有讀操作,而無寫操作,一般來說,這個全局變量是線程安全的.

若有多個線程同時執行寫操作,一般都需要考慮線程同步,否則就可能影響線程安全.

2:線程之間的死循環過程

在解決1中線程安全性問題,會引入java的鎖機制,如果一旦產生死鎖,這時就會發生不可想象的事情.

假如有三個線程,主線程main,和二個子線程A  B; 還有二個鎖lock1, lock2

二個子線程在跑的時候,假如線程A在執行的時候需要獲取鎖lock1, 在執行代碼時又需要獲取鎖lock2, 

線程B它需要獲取鎖lock2,在執行代碼的時候又需要獲取鎖lock1.

而在多線程中就可能發生這樣的事情, 線程A一直在等鎖2釋放,而線程B一直在等鎖lock1釋放.這樣線程AB就會出現死鎖現象,而這時main線程需要lock1或者Lock2的話,這樣就一直獲取不了,這就主線程就會阻塞.

(3)線程太多了內存不足的情發生

因爲每創建一個線程,在運行這個線程的時候都會爲它分配一定資源,而且在創建的時候也是很耗性能的,所以在一直創建線程的時候就會導致性能很差,慎致內存不夠用的情況發生.在開發中一般操作線程都會用到線程池來處理.

 

線程的啓動

啓動線程有的方式

1: Thread thred = new Thread();  thread.start();

2: X implements Runnable;    Thread thred =   new Thread(new X());  thread.start();

3: MyCallable implements  Callable ;使用Callable的時候又會涉及到FutureTask用法如下

        FutureTask<String> future = new FutureTask<>(callable);
        Thread thread = new Thread(future);
        thread.start();

 

線程如何停止

首先開戶一個線程

 public static void main(String[] args) {
        Thread thread = new MyThread();
        thread.start();
        try {
            Thread.sleep(20);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        thread.interrupt();
} 

thread.interrupt()使用線程的這個方法 

  
 public static class MyThread extends Thread {
        @Override
        public void run() {
            super.run();
            String name = Thread.currentThread().getName();
            while (!isInterrupted()) {
                System.out.println(name + " === is running");
            }
        }
    }

然後執行thread.interrupt()就可以.

如果在while循環裏有sleep的話,就得多加一行代碼 ,如下

    public static class MyThread extends Thread {
        @Override
        public void run() {
            super.run();
            String name = Thread.currentThread().getName();
            while (!isInterrupted()) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    System.out.println(name + " " + e.getMessage());
                    interrupt();
                }
                System.out.println(name + " === is running");
            }
        }
    }

因爲sleep當發生異常的時候,會重置isInterrupt這個返回值

 

sleep wait yield的區別

sleep:

1讓該線程進入阻塞狀態,告訴系統在指定時間內不要調試該線程,它會讓出執行權給其它線程., 到時間後自動恢復,

2當線程處於上鎖的時候,這個方法不會釋放鎖,只會釋放CPU的調試權. 當時間到後,也不一定會立馬執行,什麼時候執行這個取決於系統的調試.

3:執行這個方法時必須捕獲異常,因爲當其它線程調用了這個線程的interrupt()方法時就會拋出InterruptedException這個異常.

wait:

1: 這個方法是Object裏的一個方法,執行它時會讓該線程進入阻塞狀態

2:當這個線程處於上鎖狀態時,它會釋放這個鎖以及讓出cpu的調度權,

3:和它搭配的方法有notify(),notifyAll().執行這二個方法就會讓等待的線程被激活,但也不是一定會立馬執行,得等cpu的調試,如果有鎖的話還得等獲取鎖才能繼續執行,

4:wait()方法,notify(),notiftAll()是用於協調多線程對共享數據的存取,所以只能在同步方法或者同步塊中使用,否則拋出IllegalMonitorStateException。

yield

1:該方法與sleep()類似,都是可以讓當前正在運行的線程暫停,

2:區別在於yield()方法不會阻塞該線程,它只是將線程轉換成就緒狀態,讓系統的調度器重新調度一次,並且yield()方法只能讓優先級相同或許更高的線程有執行的機會。

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