1. 程式人生 > 其它 >java 函式式介面 Functional Interface

java 函式式介面 Functional Interface

執行緒的概念

程序是系統進行資源分配和排程的基本單位,執行緒則是程序的一個執行路徑,一個程序中至少有一個執行緒,程序中的多個執行緒共享程序的資源。真正佔用 CPU 的是執行緒,執行緒是 CPU 分配的基本單位。

Java 經常以 Main 函式作為程式執行的入口,Main 函式所在的執行緒就是程序中的一個執行緒,一般稱為主執行緒。在 Java 中多個執行緒共享程序的堆和方法區,但是每個執行緒有自己的程式計數器和棧。

執行緒建立的方式

  • 繼承 Thread 方式
    publicclassThreadStudyextendsThread{
    @Override
    publicvoidrun(){
    System.out.println(Thread.currentThread.getName());
    }
    }
    //啟動方式

    ThreadthreadStudy=newThreadStudy();
    threadStudy.start();
  • 實現 Runnable 介面方式
    publicclassRunnableTaskStudyimplementsRunnable{
    @Override
    publicvoidrun(){
    System.out.println(Thread.currentTread.getName());
    }
    }
    //啟動方式
    RunnableTaskStudytaskStudy=newRunnableTaskStudy();
    Threadthread1=newThread(taskStudy);
    Threadthread2=new
    Thread(taskStudy);
    thread1.start();
    thread2.start();
  • 實現 Callable 介面,該方式可以獲取返回值
    publicclassCallableTaskStudyimplementsCallable<String>{
    @Override
    publicvoidcall()throwsException{
    return"hello";
    }
    }

    //啟動
    FutureTask<String>futureTask=newFutureTask<>(newCallableStudy());
    Threadthread=newThread(futureTask);
    thread.start();
    try
    {
    Stringresult=futureTask.get();
    LOGGER.info("Resultis"+result);
    }catch(InterruptedException|ExecutionExceptione){
    LOGGER.info(e.getMessage());
    throwe;
    }

執行緒通知與等待

  • 當一個執行緒呼叫一個共享變數的 wait() 方法後,該執行緒被阻塞掛起,直到下面幾件事情發生返回:
    1. 其它執行緒呼叫了該共享變數的 notify(), notifyAll() 方法。
    2. 其它執行緒呼叫了該執行緒的 interrupt() 方法,該執行緒丟擲 InterruptedException 異常後返回。

    呼叫共享變數的 wait() 方法前,必須先獲取該共享變數的監視器鎖。

  • 一個執行緒呼叫了共享變數的 notify() 方法時後,會喚醒一個在該共享變數上呼叫 wait() 系列方法後被掛起的執行緒

    被喚醒的執行緒不能馬上從 wait() 方法返回並繼續執行,它必須在獲取了共享變數的監視器鎖之後才可以返回。

  • 程式碼實現

    程式碼實現需要注意的地方是在判斷是否滿足執行條件時需要使用 while 迴圈來防止虛假喚醒

    staticclassPurchaseThreadextendsThread{
    privatestaticfinalLoggerLOGGER=Logger.getLogger(PurchaseThread.class.toString());

    privatefinalResourceresource;

    publicPurchaseThread(Resourceresource){
    this.resource=resource;
    }

    @Override
    publicvoidrun(){
    try{
    resource.purchase();
    }catch(InterruptedExceptionexp){
    LOGGER.severe(exp.getMessage());
    }
    }
    }

    staticclassSaleThreadextendsThread{
    privatestaticfinalLoggerLOGGER=Logger.getLogger(SaleThread.class.toString());

    privatefinalResourceresource;

    publicSaleThread(Resourceresource){
    this.resource=resource;
    }

    @Override
    publicvoidrun(){
    try{
    resource.sale();
    }catch(InterruptedExceptionexp){
    LOGGER.severe(exp.getMessage());
    }
    }
    }

    staticclassResource{
    privatestaticfinalLoggerLOGGER=Logger.getLogger(Resource.class.toString());

    privatestaticfinalintMAX_SIZE=10;

    privatefinalDeque<String>products;

    publicResource(Deque<String>products){
    this.products=products;
    }

    publicvoidpurchase()throwsInterruptedException{
    synchronized(products){
    while(products.size()==MAX_SIZE){
    products.wait();
    }
    while(products.size()<MAX_SIZE){
    products.addLast(UUID.randomUUID().toString());
    }
    products.notifyAll();
    }
    }

    publicvoidsale()throwsInterruptedException{
    synchronized(products){
    //這裡需要通過while迴圈來防止虛假喚醒,如果這裡使用if作為判斷,當執行緒醒來之後就直接執行後面的邏輯了
    while(products.size()==0){
    products.wait();
    }
    LOGGER.info(products.removeLast());
    products.notifyAll();
    }
    }
    }

執行緒中斷

  • interrupt() 方法

    A 執行緒可以呼叫 B 執行緒的 interrupt() 方法來將 B 執行緒的中斷標誌位設定為 true 並返回,這裡並不會影響 B 執行緒的執行。如果 B 呼叫了 wait() 系列函式,join() 方法,sleep() 方法而被掛起,這個時候 A 呼叫 B 執行緒的 interrupt() 方法,執行緒 B 會在呼叫方法出丟擲 InterruptedException 異常並返回。

  • isInterrupted()

    檢測當前執行緒是否被中斷

  • interrupted()

    檢測當前執行緒被中斷,如果當前執行緒被中斷,則清除中斷標誌位。

  • 程式碼實現
    staticclassPrintThreadextendsThread{
    privatestaticfinalLoggerLOGGER=Logger.getLogger(PrintThread.class.toString());

    @Override
    publicvoidrun(){
    while(!Thread.currentThread().isInterrupted()){
    LOGGER.info("PrintYes");
    try{
    TimeUnit.SECONDS.sleep(5);
    }catch(InterruptedExceptionexp){
    //當休眠時被中斷會丟擲中斷異常
    LOGGER.severe(exp.getMessage());
    break;
    }
    }
    }
    }

    PrintThreadthread=newPrintThread();
    thread.start();
    TimeUnit.SECONDS.sleep(1);
    //這裡中斷執行緒
    thread.interrupt();
    LOGGER.info("Mainthreadisover.");