簡體   English   中英

在一段時間內運行代碼的更好方法

[英]A better way to run code for a period of time

我需要在預定義的時間內運行一些代碼,當時間到了需要停止時。 目前我正在使用TimerTask來允許代碼執行一段時間,但這會導致代碼創建無窮無盡的線程,而這只是效率不高。 還有更好的選擇嗎?

當前代碼;

// Calculate the new lines to draw 
            Timer timer3 = new Timer();
            timer3.schedule(new TimerTask(){
                public void run(){
                    ArrayList<String> Coords = new ArrayList<String>();
                    int x = Float.valueOf(lastFour[0]).intValue();
                    int y = Float.valueOf(lastFour[1]).intValue();
                    int x1 = Float.valueOf(lastFour[2]).intValue();
                    int y1 = Float.valueOf(lastFour[3]).intValue();
                    //Could be the wrong way round (x1,y1,x,y)?
                    Coords = CoordFiller.coordFillCalc(x, y, x1, y1);
                    String newCoOrds = "";
                    for (int j = 0; j < Coords.size(); j++)
                    {
                        newCoOrds += Coords.get(j) + " ";
                    }
                    newCoOrds.trim();
                    ClientStorage.storeAmmendedMotion(newCoOrds);

                }

            }
            ,time);

如果您使用的是Java5或更高版本,請考慮ScheduledThreadPoolExecutorFuture 使用前者,您可以安排在指定的延遲之后或以指定的時間間隔運行任務,從而更可靠地接管Timer的角色。

Timer工具管理延遲(“在100毫秒內運行此任務”)和定期(“每10毫秒運行此任務”)任務的執行。 但是, Timer有一些缺點,應該將ScheduledThreadPoolExecutor視為其替代品。 [...]

Timer只創建一個用於執行計時器任務的線程。 如果定時器任務運行時間太長,其他TimerTask的定時精度可能會受到影響。 如果重復定時TimerTask被安排每10毫秒運行而另一個TimerTask需要40毫秒才能運行,那么定期任務(取決於它是以固定速率還是固定延遲進行調度)在長時間運行后會快速連續調用四次任務完成,或完全“錯過”四個調用。 計划的線程池通過允許您提供多個線程來執行延遲和定期任務來解決此限制。

Timer另一個問題是,如果TimerTask拋出未經檢查的異常,它表現不佳。 Timer線程沒有捕獲異常,因此從TimerTask拋出的未經檢查的異常終止了定時器線程。 在這種情況下, Timer也不會恢復線程; 相反,它錯誤地假設整個Timer被取消了。 在這種情況下,已經調度但尚未執行的TimerTask永遠不會運行,並且無法安排新任務。

Java Concurrency in Practice ,第6.2.5節。

並且Future 可以被約束為在指定時間內最多運行 (如果無法及時完成則拋出TimeoutException )。

更新

如果您不喜歡上述內容,可以讓任務測量自己的執行時間,如下所示:

int totalTime = 50000; // in nanoseconds
long startTime = System.getNanoTime();
boolean toFinish = false;

while (!toFinish) 
{
    System.out.println("Task!");
    ...
    toFinish = (System.getNanoTime() - startTime >= totalTime);
}

[...]目前我正在使用TimerTask來允許代碼執行一段時間[...]

計時器任務永遠不會停止當前正在運行的任務。 實際上,它的唯一目的是一遍又一遍地重啟任務。

沒有與執行任務的緊密合作,沒有簡單的方法來解決這個問題。 最好的方法是讓任務監視它自己的執行,並確保它在時間結束時返回(終止)。

如果停止你意味着程序必須退出,解決方案是為你的處理創建一個線程並將其標記為守護進程,啟動它並在主線程中休眠所需的時間,然后只需從main()方法返回。

抓住,如果停止,你的意思是停止處理。

還應該注意,通常你只需要創建一個Timer()。 從代碼片段我猜你正在創建多個Timer()對象。

計划方法中的時間是運行時間,而不是運行時間。

考慮在for循環之前設置一個開始時間,如果超過了時間限制,則在for循環中放置一個中斷。

long startedAt = System.currentTimeMillis();
long finishedCorrectly = true;
for (int j = 0; j < Coords.size(); j++) {
  newCoOrds += Coords.get(j) + " ";
  if ((System.currentTimeMillis() - startedAt) > MAX_TIME_TO_RUN) {
    finishedCorrectly = false;
    break;
  }
}

暫無
暫無

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

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