簡體   English   中英

Java 中只有最近的任務 ExecutorService

[英]Only most recent task ExecutorService in Java

我想在 Java 中創建一個ExecutorService ,當給定一個任務時,它將停止並丟棄它的當前任務(如果有當前任務)並執行給定的任務。 當一個新任務被賦予這個ExecutorService ,總是因為之前的任務變得無關緊要,不再值得執行。

Java 中是否有一種內置方法可以做到這一點,還是我應該自己實現這種行為? 還是有另一種方法在這種情況下效果更好?

這是一個有趣的問題。 我對核心ExecutorService實現有了更深入的了解。 謝謝!


不使用ExecutorService解決

根據您所提到的,您將最多有一個線程執行任務,最多有一個任務掛起,因為我們只對最后提交的任務感興趣。 你真的需要一個ExecutorService嗎?

您可以將下一個任務保存在 POJO 對象的static AtomicReference字段中。 由於我們只對最新的任務感興趣,因此任務生產者可以簡單地替換AtomicReference的對象。 當前任務執行完成后,任務使用者可以從該字段中獲取。 該字段必須是:

  • static因為該字段應該只有一個實例
  • AtomicReference因為多個線程可能正在嘗試設置下一個任務。

使用ExecutorService解決

但是,如果你仍然想走ExecutorService方式,你可以試試這個。 創建一個只有一個線程(核心和最大線程)的ThreadPoolExecutor並為其提供一個BlockingQueue實現,該實現在添加新線程后立即“忘記”其所有元素。 這是一個示例測試代碼。

public class OnlyOneTask{
    public static void main( String[] args ){
        ExecutorService svc = Executors.newSingleThreadExecutor();
        
        /* A BlockingQueue that immediately "forgets" all tasks it had as soon as a new one is "offered". */
        BlockingQueue<Runnable> Q = new ArrayBlockingQueue<Runnable>( 1 ) {
            private static final long serialVersionUID = 1L;
            
            /* Forget the current task(s) and add the new one
             * TODO These 2 steps may need synchronization. */
            public boolean offer( Runnable e) {
                clear();    
                return super.offer( e );
            }
        };
        
        try {
            /* A ThreadPoolExecutor that uses the queue we created above. */
            svc = new ThreadPoolExecutor( 1, 1, 5000, TimeUnit.MILLISECONDS, Q );
            
            for( int i = 0; i < 100; i++ ) {
                /* Our simple task. */
                int id = i;
                Runnable r = () -> {
                    System.out.print( "|" + id + "|" );
                };
                
                svc.submit( r );
                
                /* A delay generator. Otherwise, tasks will be cleared too fast. */
                System.out.print( " " );
            }
        }
        finally {
            svc.shutdown();
            try{
                svc.awaitTermination( 10, TimeUnit.SECONDS );
            }
            catch( InterruptedException e ){
                e.printStackTrace();
            }
        }
    }
}

這個示例類只是為了讓我了解我認為可行的方法。 您肯定需要改進此實現中的以下缺點:

  • 第一個任務無論如何都會執行,因為它會立即被ExecutorService (這就是為什么下一點變得重要的原因。)
  • 如有必要,必須將可中斷性/可取消性引入正在運行的任務中

暫無
暫無

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

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