日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

面试必备:多线程学习(一)

發布時間:2023/12/10 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 面试必备:多线程学习(一) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

這是2020年“水”的第23篇文章

面試中,多線程并發問題基本上是必問的,所以,不背上個線程相關的問題,都不好意思出去面試了。

一提到多線程,相信大部分小伙伴首先想到的一定是 SynchronizeLock,再就是volatileconcurrent并發包,厲害點的小伙伴呢,還能再跟面試官吹吹Synchronizevolatile的區別跟原理,以及并發包常用的數據結構,例如之前提到的 ConcurrentHashMap

好了,廢話不多說,本篇就以面試為出發點,看看多線程到底要準備哪些傻吊知識點。

1、多線程的創建方式

  • 繼承Thread
  • 實現Runnable接口
  • 實現Callable接口
  • 一共3種創建方式,不要問哪個好,問就是接口形式的好,因為實現接口的方式比繼承類的方式更靈活,也能減少程序之間的耦合度,面向接口編程也是設計模式6大原則的核心,但是,是選擇實現Runnable,還是Callable,就要根據自己情況選擇了。

    延伸補充:Runnable跟Callable區別?

    如果上邊的問題回答了Runnable、Callable,那么就要準備好關于兩者的區別?什么?沒用過Callable?背就完事了。

    Runnable沒有返回值,需要做的事情就是去執行run()方法,執行完就完了。
    Callable有返回值,該返回值是Callable接口中的call()方法,是一個泛型,和Future、FutureTask配合可以用來獲取異步執行的結果。

    簡單看一下代碼:

    Callable?callable?=?new?Callable()?{
      @Override
      public?String?call()?throws?Exception?
    {
      ????Thread.sleep(5000);
      ????return?"我是call方法返回值";
      }
    };
    Future?future?=?executor.submit(callable);
    System.out.println("獲取返回值:?"+future.get());

    看完上方代碼,如果問到Callable接口會有哪些應用場景應該會答了吧?

    2、wait() 和 notify() 的理解和使用?

    有時候面試官會先延伸一下它的出處,比如,你能說一下Object類都有哪些方法嗎?

    只要你提到了 wait() 跟 notify() || notifyAll() 那么基本就會問相關的內容了。

    wait和notify是用來讓線程進入等待狀態以及使線程喚醒的兩個操作。

    理解:

    wait、notify 屬于 Object 基礎類,所以每個對象都有 wait、notify 的功能,也就是每個對象都有鎖的權利;但是在使用此類方法的時候,一定要對競爭資源進行加鎖操作,獲得這個鎖對象的控制權,比如放在 Synchronize(obj) 代碼塊中,如果不加鎖的話,則會報 IllegalMonitorStateException 異常。

    使用:

    public?class?Test?{

    ????public?static?void?main(String[]?args)?{
    ????????Object?obj?=?new?Object();
    ????????Thread?thread1?=?new?Thread(()?->?{
    ????????????synchronized?(obj)?{
    ????????????????try?{
    ????????????????????System.out.println("1-before?wait");
    ????????????????????obj.wait();
    ????????????????????System.out.println("1-after?wait");
    ????????????????}?catch?(Exception?e)?{
    ????????????????????System.out.println(String.format("1-catch?:%s.?interrupt狀態:?%s",e.toString(),Thread.currentThread().isInterrupted()));
    ????????????????????Thread.currentThread().interrupt();
    ????????????????????System.out.println("設置標志位后interrupt狀態:?"+?Thread.currentThread().isInterrupted());

    ????????????????}
    ????????????}
    ????????});

    ????????thread1.start();
    ????????try?{
    ????????????Thread.currentThread().sleep(2000);
    ????????}?catch?(InterruptedException?e1)?{
    ????????????e1.printStackTrace();
    ????????}
    ????????System.out.println("線程初始interrupt狀態:"+thread1.isInterrupted());
    ????????thread1.interrupt();

    ????}
    }

    如果你不太清楚上方代碼中的 interrupt()、interrupted() 和isInterrupted() 那么可以參考這篇文章:Thread類中interrupt方法詳解

    廢話總結:

    wait和notify來自于Object基礎類;
    wait和notify是用來讓線程進入等待狀態以及使線程喚醒的兩個操作。
    wait或notify方法,使用時必須保證當前運行的線程取得了該對象的控制權。
    如果在沒有控制權的線程里執行wait或notify方法,會報IllegalMonitorStateException異常。

    3、sleep() 和 wailt() 的區別

    如果在上一個wailt、notify中沒有回答出wailt的細節的話,那么這個問題就會常問;

    首先兩者來源不同,sleep來自Thread類,而wait來自Object類。

    sleep方法和wait方法都可以用來放棄CPU一定的時間,不同點在于如果線程持有某個對象的監視器,sleep方法不會放棄這個對象的監視器,而wait方法會放棄這個對象的監視器,怎么講?

    sleep方法不會釋放鎖,調用sleep后不會出讓系統資源,典型無賴行為「占著茅坑不拉*」;而wait則是進入線程等待池等待,會出讓系統資源,其他線程可以占用CPU,就是我現在不用了,你們先用吧。

    通常wait是不會加時間限制的,因為如果wait線程的運行資源不夠,即使出來也沒用,要等待其他線程調用notify/notifyAll喚醒等待池中的所有線程,才會進入就緒隊列等待系統分配資源。

    而sleep(秒)可以用指定時間使它自動喚醒過來,如果時間不到只能調用interrupt()強行打斷。比如上端代碼中我用到了 thread1.interrupt(); 方法,作用就是強行打斷。

    使用范圍不同:wait只能在同步控制方法或者同步控制塊里面使用,而sleep可以在任何地方使用。所以你看到的只要出現wait必出現Synchronize,而sleep可以到處使用。

    廢話總結:

    所屬類不同:sleep() 來自Thread;wailt() 來自 Object
    是否釋放鎖:sleep() 不會釋放鎖;wailt() 會釋放鎖
    用法不同:sleet時間到了會自動恢復;wailt() 可以使用notigy()/notigyAll()直接喚醒
    使用范圍不同:sleep() 在任何地方可用;wait() 需要結合 Synchronize使用
    作用不同:sleep() 通常被用于暫停執行;wait() 通常被用于線程間交互/通信

    4、如何保證多線程安全?

  • 使用安全類,比如 java.util.concurrent 并發包下的類;
  • 使用鎖,比如自動Synchronize,手動鎖 Lock
  • 如上兩點只是盡量做到線程安全,或者說目前被建議以及常用的,但做到絕對的線程安全通常需要付出許多額外代價,Java中標注自己是線程安全的類,實際上絕大多數都不是線程安全的,不過絕對線程安全的類,Java中也有,比方說CopyOnWriteArrayList、CopyOnWriteArraySet

    廢話總結:

    如果你的代碼,在多線程下執行和在單線程下執行,永遠都能得到一樣的結果,那么你的代碼就是線程安全的。

    5、Synchronize跟Lock區別

    提到Synchronize就不得不扯上Lock,冤家路窄,面試總是會問。

    Synchronize:java中提供的一個并發控制的關鍵字,自動鎖、重量級。主要用在同步方法和同步代碼塊中,也就是說,synchronized既可以修飾方法也可以修飾代碼塊。被synchronized修飾的代碼塊及方法,在同一時間,只能被單個線程訪問。應用場景:商品下單,商品庫存的修改。

    Lock:是一個類,確切說是一個接口類,其實現類可以實現同步訪問。Lock為輕量級、手動鎖,能夠實現synchronized所實現的功能,但Lock相對更加靈活,可以被繼承、可以有方法、可以有各種各樣的類變量。

    轉自網上的區別表格:

    類別synchronizedLock
    存在層次Java的關鍵字,在jvm層面上是一個類
    鎖的釋放1、以獲取鎖的線程執行完同步代碼,釋放鎖 2、線程執行發生異常,jvm會讓線程釋放鎖在finally中必須釋放鎖,不然容易造成線程死鎖
    鎖的獲取假設A線程獲得鎖,B線程等待。如果A線程阻塞,B線程會一直等待分情況而定,Lock有多個鎖獲取的方式,具體下面會說道,大致就是可以嘗試獲得鎖,線程可以不用一直等待
    鎖狀態無法判斷可以判斷
    鎖類型可重入 不可中斷 非公平可重入 可判斷 可公平(兩者皆可)
    性能少量同步大量同步

    個人補充:

    如果單單寫兩者,完全可以寫一篇文章,由于本篇是出于面試準備的,所以面試官問到時,簡單說一下兩者的作用,以及各自的應用場景即可『經驗初級』,當然,如果你有特地看過源碼的話,自然是建議你引導面試官問你原理,你懂得~ 不過話說回來,synchronized 原理還是有必要了解的~

    廢話總結:

    1、Synchronized為java關鍵字,由JVM控制;Lock為接口類,由JDK實現;
    2、Synchronized重量級、自動鎖,Lock輕量級、手動鎖;
    3、發生異常時,Synchronized會自動釋放鎖,Lock需要手動在finally釋放鎖,不釋放很容易造成死鎖;
    4、Lock更加靈活,能夠響應中斷,讓等待狀態的線程停止等待,synchronized不行;
    5、通過Lock可以知道線程是否成功獲得了鎖,synchronized不行;

    最后

    本篇為多線程面試準備的第一篇,標簽為左側分欄的:面試相關

    目前只準備了5個小問題,會結合自己近期的準備持續更新下一篇。

    博客地址:https://www.cgblog.com/niceyoo

    如果覺得這篇文章有丶東西,不防關注一下我,關注是對我最大的鼓勵~

    18年專科畢業后,期間一度迷茫,最近我創建了一個公眾號用來記錄自己的成長。

    總結

    以上是生活随笔為你收集整理的面试必备:多线程学习(一)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。