簡體   English   中英

執行程序關閉等待終止不起作用

[英]Executor Shutdown await termination not working

我正在調用等待終止,因為我需要在調用意圖之前完成前兩個 Runnables。 但是它不起作用,意圖被調用,當我調用 navEngine.getRoutes 時,navEngine 是 null。 執行器服務初始化如下:

public static ExecutorService buildExecutor = Executors.newFixedThreadPool(2);
Runnable runnable = new Runnable() {
                        @Override
                        public void run() {
                            navEngine = new NavigationManager(start, destination, selectedBuilding);
                        }
                    };
                    buildExecutor.execute(runnable);
                    Boolean isVisionImpaired = defaultPreferences.getString(kSightSetting, "Vision Impaired").equalsIgnoreCase("Vision Impaired");
                    if (isVisionImpaired) {
                        Runnable dRunnable = new Runnable() {
                            @Override
                            public void run() {
                                String[] dxfs = mapManager.generateDs( new String[] { selectedBuilding.getBuildingID() });
                                navEngine.setD_for_these_buildings(dxfs);
                            }
                        };
                        buildExecutor.execute(dRunnable);
                    }

                }
                buildExecutor.shutdown();
                try {
                    buildExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Intent intent = new Intent(ChooseDestinationActivity.this, DefineRouteActivity.class);

任何建議都會很棒。

我已經看了一些可能的解決方案,它們是:

  1. 增加等待終止時間

  2. 將 try/catch 替換為

    while (.buildExecutor;isTerminated()). { //do nothing } Intent(...)
  3. 創建可調用列表添加在此處使用 Executors.callable 添加您的可運行對象,然后調用 invokeAll()

     List<Callable<Object>> calls = new ArrayList<Callable<Object>>(); calls.add(Executors.callable(your runnable here)); buildExecutor.invokeAll(calls); buildExecutor.shutdown(); Intent(...)

PS我不是本地人並發,但我已經嘗試了我給出的所有解決方案,我也很感激所有建議)

警告:我不做 Android 工作。 我說的是標准 Java。

重現問題的細節不足

您的 runnables 和 executor 服務的基礎是正確的。 下面是您的代碼的簡化版本來說明這一點。

所以我懷疑你的問題出在其他地方。 您沒有顯示代碼的所有重要部分。 特別缺乏的是navEngine的定義,這似乎是您投訴的根源。

package work.basil.example.threading;

import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class App
{
    public static void main ( String[] args )
    {
        App app = new App();
        app.demo();
    }

    private void demo ( )
    {
        System.out.println( "`demo` method ending. " + Instant.now() );
        ExecutorService executorService = Executors.newFixedThreadPool( 2 );

        // Navigation Manager work.
        Runnable navManTask = new Runnable()
        {
            @Override
            public void run ( )
            {
                System.out.println( "navManTask - beginning. Will sleep to simulate lengthy work. " + Instant.now() );
                try
                {
                    Thread.sleep( Duration.ofSeconds( 10 ).toMillis() );
                }
                catch ( InterruptedException e )
                {
                    System.out.println( "navManTask - sleep interrupted. Ending this task prematurely. " + Instant.now() );
                    return;
                }
                System.out.println( "navManTask - ending. " + Instant.now() );
            }
        };
        executorService.execute( navManTask );

        // Vision Impaired work.
        boolean isVisionImpaired = true;
        if ( isVisionImpaired )
        {
            Runnable visionTask = new Runnable()
            {
                @Override
                public void run ( )
                {
                    System.out.println( "visionTask - beginning. Will sleep to simulate lengthy work. " + Instant.now() );
                    try
                    {
                        Thread.sleep( Duration.ofSeconds( 10 ).toMillis() );
                    }
                    catch ( InterruptedException e )
                    {
                        System.out.println( "visionTask - sleep interrupted. Ending this task prematurely. " + Instant.now() );
                        return;
                    }
                    System.out.println( "visionTask - ending. " + Instant.now() );
                }
            };
            executorService.execute( visionTask );

            System.out.println( "`demo` method asking  executor service to shut down. " + Instant.now() );
            executorService.shutdown();
            try
            {
                System.out.println( "`main` method waiting for the executor service to shut down. " + Instant.now() );
                executorService.awaitTermination( 30 , TimeUnit.SECONDS );
            }
            catch ( InterruptedException e )
            {
                e.printStackTrace();
            }
            System.out.println( "`demo` method ending. " + Instant.now() );
        }
    }
}

其他問題

您可能還有其他並發問題。

爭用通過兩個線程訪問navEngine object

您有兩個同時訪問同一資源的線程,即變量navEngine 那里有兩個問題:可見性和線程安全。

Visibility under the Java Memory Model is where a primitive or object reference accessed across threads may show two different cached values. 一種解決方案是volatile關鍵字。 另一種解決方案可能是Atomic… class。 搜索以了解有關可見性問題的更多信息。

我們看不到 navEngine 后面的navEngine 但是,如果 class 的 object 可以跨線程操作,則必須使 class 成為線程安全的。

第二個線程取決於第一個線程

在一個線程的代碼中,您正在實例化一個 object 以放置在navEngine變量中。 在另一個線程的代碼中,您假設 object 存在。 但是您無法預測線程將以什么順序進行工作。 線程的調度實際上是任意且不可預測的,具體取決於主機操作系統和JVM的瞬時條件和 CPU 調度決策策略。 在第一個線程使用 object 引用填充變量之前,第二個線程完全有可能嘗試訪問navEngine

由於第二個 runnable 取決於第一個是否完整且成功,因此擁有兩個單獨的線程是沒有意義的。 您不妨將兩者組合成一個Runnable任務。

如果您堅持使用這兩個線程,那么您將需要將您的調用更改為execute submit submit方法返回一個Future object。 您可以使用這個Future object 來檢查第一個任務是否成功。

這是上面修改的代碼,用於捕獲提交 navMan 任務到執行器服務時返回的Future 視覺工作等待Future發出 navMan 工作完成的信號。

package work.basil.example.threading;

import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.*;

public class App
{
    public static void main ( String[] args )
    {
        App app = new App();
        app.demo();
    }

    private void demo ( )
    {
        System.out.println( "`demo` method ending. " + Instant.now() );
        ExecutorService executorService = Executors.newFixedThreadPool( 2 );

        // Navigation Manager work.
        Runnable navManTask = new Runnable()
        {
            @Override
            public void run ( )
            {
                System.out.println( "navManTask - beginning. Will sleep to simulate lengthy work. " + Instant.now() );
                try
                {
                    Thread.sleep( Duration.ofSeconds( 10 ).toMillis() );
                }
                catch ( InterruptedException e )
                {
                    System.out.println( "navManTask - sleep interrupted. Ending this task prematurely. " + Instant.now() );
                    return;
                }
                System.out.println( "navManTask - ending. " + Instant.now() );
            }
        };
        Future < String > navManFuture = executorService.submit( navManTask , "whatever" );

        // Vision Impaired work.
        boolean isVisionImpaired = true;
        if ( isVisionImpaired )
        {
            Runnable visionTask = new Runnable()
            {
                @Override
                public void run ( )
                {
                    System.out.println( "visionTask - beginning. Will sleep to simulate lengthy work. " + Instant.now() );
                    if ( navManFuture.isCancelled() )
                    {
                        System.out.println( "visionTask - Found the navMan task got cancelled. Ending this task prematurely. " + Instant.now() );
                        return;
                    }
                    try
                    {
                        System.out.println( "visionTask - Waiting for the navMan task to be done. " + Instant.now() );
                        String whatever = navManFuture.get(); // Wait for `namManTask` to get done. This code blocks here, waiting.
                        Thread.sleep( Duration.ofSeconds( 10 ).toMillis() );
                    }
                    catch ( InterruptedException e )
                    {
                        System.out.println( "visionTask - sleep interrupted. Ending this task prematurely. " + Instant.now() );
                        return;
                    }
                    catch ( ExecutionException e )
                    {
                        e.printStackTrace();
                    }
                    System.out.println( "visionTask - ending. " + Instant.now() );
                }
            };
            executorService.submit( visionTask );

            System.out.println( "`demo` method asking  executor service to shut down. " + Instant.now() );
            executorService.shutdown();
            try
            {
                System.out.println( "`main` method waiting for the executor service to shut down. " + Instant.now() );
                executorService.awaitTermination( 30 , TimeUnit.SECONDS );
            }
            catch ( InterruptedException e )
            {
                e.printStackTrace();
            }
            System.out.println( "`demo` method ending. " + Instant.now() );
        }
    }
}

項目織機

順便說一句,如果Project Loom技術在 Java 到來時,這里看到的代碼會更簡單。 在 Loom 中, ExecutorService接口也是AutoCloseable 這意味着我們可以使用方便的 try-with-resources 語法。 close方法會阻塞,直到所有提交的任務都完成/失敗/取消。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM