scheduleAtFixedRate 대 scheduleWithFixedDelay


117

ScheduledExecutorService의scheduleAtFixedRatescheduleWithFixedDelay메소드의 주요 차이점은 무엇입니까 ?

scheduler.scheduleAtFixedRate(new Runnable() {
    @Override
    public void run() {
        System.out.println("scheduleAtFixedRate:    " + new Date());
    }
}, 1, 3L , SECONDS);

scheduler.scheduleWithFixedDelay(new Runnable() {
    @Override
    public void run() {
        System.out.println("scheduleWithFixedDelay: " + new Date());
    }
}, 1, 3L , SECONDS);

그들은 정확히 같은 시간에 인쇄하고 정확히 같은 간격으로 실행되는 것처럼 보입니다.

답변:


206

메서드 Thread.sleep(1000);내 에서 호출을 추가해보세요 run()... 기본적으로 이전 실행이 종료되는 시점과 (논리적으로) 시작 되는 시점을 기준으로 일정을 예약하는 것의 차이 입니다.

예를 들어 1 시간에 한 번 고정 된 속도 로 알람이 울리도록 예약하고 알람이 울릴 때마다 10 분 정도 걸리는 커피를 마신다고 가정 해 보겠습니다 . 자정에 시작한다고 가정하면 다음과 같습니다.

00:00: Start making coffee
00:10: Finish making coffee
01:00: Start making coffee
01:10: Finish making coffee
02:00: Start making coffee
02:10: Finish making coffee

1 시간 의 고정 지연 으로 일정을 잡는 경우 다음을 수행 할 수 있습니다.

00:00: Start making coffee
00:10: Finish making coffee
01:10: Start making coffee
01:20: Finish making coffee
02:20: Start making coffee
02:30: Finish making coffee

원하는 것은 작업에 따라 다릅니다.


18
커피를 만드는 데 1 시간 이상 걸리면 fixedRate 시나리오에서 어떤 일이 발생합니까?
Brett VanderVeen 2014 년

5
@BrettVanderVeen : 문제의 집행자에 따라 다릅니다. 그것은 될 예정 시간에 -하지만 여부를 실행하는 스레드가 그 집행을 사용할 수 있는지 여부에 따라 달라집니다. 다양한 시나리오에서 이것이 어떻게 작동하는지 실험 해 보는 것이 좋습니다.
Jon Skeet 2014 년

8
@BrettVanderVeen 문서 에서 "이 작업의 실행이 해당 기간보다 오래 걸리면 후속 실행이 늦게 시작될 수 있지만 동시에 실행되지는 않습니다." 즉, 준수하는 구현은 이전 구현이 완료 될 때까지 다음 구현이 실행되는 것을 허용하지 않습니다.
M. Justin

나와 같은 초보자를 위해 표시된 출력 (커피)에 대한 작업 코드를 제공 할 수 있습니까?
MuneshSingh

@MuneshSingh : 고정 된 속도로 예약하는 것과 고정 된 지연으로 예약하는 것의 차이점을 설명하는 질문이 아닙니다. 어쨌든 이것을 직접 구현하지는 않을 것입니다. 내장 된 실행기를 사용할 것입니다.
Jon Skeet

57

호출 scheduleAtFixedRate방법의 시계열을 시각화합니다 . 마지막 실행이 기간보다 오래 걸리면 다음 실행이 즉시 시작됩니다. 그렇지 않으면 일정 시간 후에 시작됩니다.

호출 scheduleAtFixedRate 메서드의 시계열

호출 scheduleWithFixedDelay방법의 시계열 . 다음 실행은 실행 시간에 관계없이 한 실행 종료와 다음 실행 시작 사이의 지연 시간 후에 시작됩니다.

호출 scheduleWithFixedDelay 메서드의 시계열

희망이 당신을 도울 수 있습니다


scheduleAtFixedRate 시계열 다이어그램에 언급 된 "추가"단어를 이해할 수 없습니다.
MuneshSingh

1
@MuneshSingh 작업의 실행 시간이 예정된 시간보다 길다는 것을 나타 내기 위해 "추가"시간이 걸리고 다음 실행이 즉시 시작됩니다.
Viorel

@Viorel을 명확히 해주셔서 감사합니다. 이는 "기간"이 두 연속 실행 사이의 고정 된 시간 지연이 아님을 의미합니까?
MuneshSingh

1
@MuneshSingh 기간은 고정되어 있지만 현재 작업을 통과하면 중지되지 않으며이 실행과 다음 실행 사이에 지연이 없습니다. "시간 초과"를 생성하려는 경우 Future를 유지하고 다른 실행기에서 취소 할 수 있습니다. 간단히 말해서 "기간"시간이 지난 후 가능한 한 빨리 첫 번째 실행을 시작하고 다음 실행을 시작합니다 .
Viorel

4

scheduleAtFixedRate()메서드는 새 작업을 만들고 이전 작업이 완료되었는지 여부에 관계없이 매 기간마다 실행자에게 제출합니다 .

반면에이 scheduleWithFixedDelay()메서드 는 이전 작업이 완료된 후 새 작업 만듭니다 .


두 번 썼습니다. scheduleAtFixedRate:)
Vlad

3

Java Doc을 읽으면 더 명확해질 것입니다.

ScheduledFuture scheduleAtFixedRate (Runnable command, long initialDelay, long period, TimeUnit unit) 지정된 초기 지연 후 먼저 활성화되고 이후에 지정된 기간으로 활성화되는 주기적 작업을 생성하고 실행합니다. 즉, initialDelay, initialDelay + period, initialDelay + 2 * period 등으로 실행이 시작됩니다.

ScheduledFuture scheduleWithFixedDelay (Runnable command, long initialDelay, long delay, TimeUnit unit) 지정된 초기 지연 후 먼저 활성화되고 이후에 한 실행의 종료와 다음 실행의 시작 사이에 지정된 지연으로 활성화되는 주기적 작업을 생성하고 실행합니다.


1

첫 번째 스레드가 너무 오래 걸리고 주어진 기간 내에 종료되지 않은 경우 scheduleAtFixedRate에 한 가지 캐치가 있으며 첫 번째 작업이 완료되면 두 번째 연속 스레드가 시작되지 않고 첫 번째 스레드가 작업 및 gievn 기간을 완료하는 동안 즉시 시작되지 않습니다. 경과되었습니다. JVM은 다음 작업이 실행될시기를 결정합니다.

나는 이것이 당신이 방법을 선택하는 데 도움이 될 것이라고 생각합니다.


1
뭐? JVM이 결정합니까? 그게 무슨 뜻이야? 실행 파일이 문서에 따라 자체적으로 동시에 실행되지는 않지만 실행자가 결정합니다. 이는 사용자 정의 또는 표준 일 수 있습니다 ScheduledThreadPoolExecutor(그리고 후자는 잘 정의 된 동작을
가짐

아니요 15 분 간격을 주었고 첫 번째 작업이 15 분 안에 완료되지 않고 15.30 초가 걸리지 않아 두 번째 작업이 즉시 시작되지 않았기 때문에 내 응용 프로그램에서 비슷한 문제를 발견했습니다. 8 분 동안이 동작이 표준 동작이 아니기 때문에이 동작을 제어 할 수 있는지 여부를 모르겠습니다.
user1047873

교과서 작업 대기열처럼 들립니다.
Ordous

예, 실행 프로그램의 모든 스레드가 이미 작업 중이며 작업이 수행 할 작업 대기열에 포함된다는 의미입니다. ( 참고 로 해당 대기열을 보거나 실행기 스레드가 수행하는 작업을 확인하여이를 확인해야합니다). 이를 제어하는 ​​방법은 보유한 실행기 유형에 따라 다릅니다. 이 특정 작업에 대해서만 별도의 1- 스레드 실행기를 만들고 싶을 수 있습니다. 그러면 아무것도 기다리지 않습니다. 또는 현재 실행자에게 더 많은 스레드를 제공하십시오. 아니면 전략을 바꾸십시오.
Ordous 2014-07-09

0

간단한 프로그램을 작성해 보겠습니다.

import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit

var time = 0L
var start = System.currentTimeMillis()
val executor = Executors.newScheduledThreadPool(1)
executor.scheduleWithFixedDelay({
    if (time >= 12_000L) {
        executor.shutdown()
    } else {
        Thread.sleep(2000L)
        val now = System.currentTimeMillis()
        time += now - start
        System.out.println("Total $time delay ${now - start}\n")
        start = now
    }
}, 0L, 1000L, TimeUnit.MILLISECONDS)

결과를 확인하십시오.

| scheduleWithFixedDelay |   scheduleAtFixedRate  |
|:----------------------:|:----------------------:|
| Total 2001 delay 2001  | Total 2003 delay 2003  |
| Total 5002 delay 3001  | Total 4004 delay 2001  |
| Total 8003 delay 3001  | Total 6004 delay 2000  |
| Total 11003 delay 3000 | Total 8004 delay 2000  |
| Total 14003 delay 3000 | Total 10005 delay 2001 |
|          ---           | Total 12005 delay 2000 |

실행 시간이 기다리는 것보다 큽니다.

scheduleWithFixedDelay 는 지연을 유지합니다.
scheduleAtFixedRate 는 지연을 제거합니다.


-1
scheduledExecutorService.scheduleAtFixedRate(() -> {
        System.out.println("runnable start"); try { Thread.sleep(5000);  System.out.println("runnable end");} catch
     (InterruptedException e) { // TODO Auto-generated catch block
      e.printStackTrace(); }}, 2, 7, TimeUnit.SECONDS);



     scheduledExecutorService.scheduleWithFixedDelay(() -> {
     System.out.println("runnable start"); try { Thread.sleep(5000); System.out.println("runnable end");} catch
     (InterruptedException e) { // TODO Auto-generated catch block
     e.printStackTrace(); } }, 2, 7, TimeUnit.SECONDS);

실행 만하면 차이를 알 수 있습니다. 감사합니다


1
코드가 OP의 문제를 어떻게 해결하는지 설명하십시오. :)
Yash
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.