2012-02-15 49 views
2

我的問題是:我有一個類接受目錄中的文件。每當第一個對象到達時,它啓動一些定時器對目錄中的所有文件執行壓縮,這些文件在接下來的60秒內到達。Java:計時器或ScheduleExecutorService用於計算繁忙窗口中的點擊次數?

這就提出了兩個要求:

1)我需要能夠檢查是否在新文件到達「倒計時」已經在運行。我不希望file2在file1之後15秒到達,然後它們在45秒後被壓縮在一起,只有在第一次完成(到一個空目錄)15秒後觸發第二個計劃任務。

2)智能配料/非恆定輪詢。例如,如果file1在時間= 0到達,file2在時間= 59s到達,它們將被壓縮在一起。但是,如果file3在時間= 89s之前沒有到達,並且file4在時間= 129s到達,我想確保下一個「壓縮」操作不在定時器= 120s發生,而是在定時器= 149s(60秒之後file3抵達)。

換句話說:只有一個定時器/倒計時應該運行。如果它是自壓縮以來的第一個文件,它應該觸發一個新的文件,否則它應該被忽略。

我正在研究java.util.Timer和Java.util.concurent.ScheduledExecutorService作爲解決方案,但都似乎建立了多個進程,我試圖避免。

有沒有更好的解決方案呢?

+0

您如何收到文件已經「抵達」的通知? 「到達」意味着什麼 - 這是否意味着該文件已被完全編寫並由任何應用程序創建它關閉? – 2012-02-15 14:55:03

+0

我的課程是通過一個文件,然後將其移動到適當的目錄並在壓縮之前檢查定時器/倒計時。 – Bing 2012-02-15 15:04:04

回答

1

下面是一個例子代碼:

private Thread countDownThread; 

public synchronized void onNewFile() { 
    startCountDownThreadIfNotYetRunning(); 
} 

public synchronized void resetThread() { 
    if(uncompressedFilesExist()) { 
     startCountDownThreadIfNotYetRunning(); 
    } 
} 

public synchronized void startCountDownThreadIfNotYetRunning() { 
    if(countDownThread == null) { 
     new Thread(new CompressionTask()).start(); 
    } 
} 

private class CompressionTask implements Runnable { 
    @Override 
    public void run() { 
     try { 
      Thread.sleep(60 * DateUtils.MILLIS_PER_SECOND); 
      compressDirectoryContents(); 
      resetThread(); 
     } 
     catch (InterruptedException e) { } 
    } 
} 
  1. onNewFile()被調用它試圖啓動一個新的countDownThread,如果它尚未運行。

  2. 此線程等待60秒並開始壓縮。

  3. 最後一步resetThread()有點棘手。如果我們只是打電話:

    countDownThread = null; 
    

    該代碼不會線程安全。首先對countDownThread所做的更改可能不會被其他線程看到。此外,如果在compressDirectoryContents()和簡單分配之間出現新文件,它將會丟失。這就是爲什麼所有操作都是​​使用相同的鎖。

    因爲onNewFile()resetThread()都被相同的鎖保護,所以不可能出現新文件,但是不啓動倒計時線程。

注意,你不需要任何花哨Timer S或ScheduleExecutorService - 創建一個單獨的線程分秒不矯枉過正。

+0

謝謝,這看起來好像會起作用(現在試圖實現它)。後續:如果滿足文件計數,是否可以強制觸發CompressionTask運行? (說10個文件到達下60秒左右,所以當11日的文件到達時,不管它是第一個計數器將結束之前觸發它的時候了,並重新啓動在60秒計數器?) – Bing 2012-02-15 16:34:40

+0

@myingling:是的,在幾個方面,但我會將實施細節留給你:-)。我認爲最容易,但有點hacky的方式是調用'countDownThread.interrupt()'。但它增加了解決方案的一些複雜性。也許'Queue'會幫助你? – 2012-02-15 16:42:31