java : 특정 시간 (초) 후에 함수 실행


148

5 초 후에 실행하려는 특정 기능이 있습니다. Java로 어떻게 할 수 있습니까?

javax.swing.timer를 찾았지만 사용법을 이해할 수 없습니다. 이 클래스가 제공하는 것보다 더 간단한 방법을 찾고있는 것 같습니다.

간단한 사용 예를 추가하십시오.


5 초 동안 기다렸다가 실행하고 싶습니까? 아니면 5 초 후에 다른 작업을 계속하고 싶습니까?
위스키 시에라

다른 일을 계속하고 싶습니다
ufk

답변:


229
new java.util.Timer().schedule( 
        new java.util.TimerTask() {
            @Override
            public void run() {
                // your code here
            }
        }, 
        5000 
);

편집하다:

javadoc 는 말한다 :

Timer 객체에 대한 마지막 실시간 참조가 사라지고 모든 미해결 작업이 실행을 완료하면 타이머의 작업 실행 스레드가 정상적으로 종료됩니다 (가비지 수집 대상이 됨). 그러나이 문제가 발생하는 데 시간이 오래 걸릴 수 있습니다.


1
해당 코드를 실행하면 스레드가 누출됩니다. 완료되면 타이머를 청소하십시오.
skaffman

1
@ skaffman : javadoc에서 문장을 추가했습니다. 당신은 정말 일정을 호출 한 후 정리해야합니까?
tangens

1
괜찮을 수도 있지만 그렇지 않을 수도 있습니다. 해당 코드 조각을 여러 번 실행하면 스레드를 정리할 수단없이 느슨한 스레드가 발생합니다.
skaffman

5
import java.util.Timer; import java.util.TimerTask;이것이 아니라는 것을 더 분명하게 만들 수 있습니다 javax.swing.Timer. / 참고로 Swing (및 실제로 AWT)을 사용하는 경우 비 EDT (Event Dispatch Thread) 스레드에서 구성 요소를 변경하는 작업을 수행해서는 안됩니다 ( java.util.Timer작업이 나쁘다, javax.swing.Timer좋은 동작).
Tom Hawtin-tackline

2
@PaulAlexander docs에 따르면-run cancel메소드의 끝에서 timer의 메소드를 호출 하면 TimerTasks의 실행 스레드가 지워집니다.
Dandalf

58

이 같은:

// When your program starts up
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();

// then, when you want to schedule a task
Runnable task = ....    
executor.schedule(task, 5, TimeUnit.SECONDS);

// and finally, when your program wants to exit
executor.shutdown();

Executor풀에 더 많은 스레드가 필요한 경우 대신 사용할 수있는 다양한 다른 팩토리 메소드 가 있습니다.

그리고 완료되면 실행 프로그램을 종료하는 것이 중요합니다. 이 shutdown()메소드는 마지막 작업이 완료되면 스레드 풀을 완전히 종료하고 이러한 상황이 발생할 때까지 차단합니다. shutdownNow()스레드 풀을 즉시 종료합니다.


24

사용 예 javax.swing.Timer

Timer timer = new Timer(3000, new ActionListener() {
  @Override
  public void actionPerformed(ActionEvent arg0) {
    // Code to be executed
  }
});
timer.setRepeats(false); // Only execute once
timer.start(); // Go go go!

이 코드는 한 번만 실행되며 3000ms (3 초) 내에 실행됩니다.

camickr가 언급했듯이 짧은 소개를 보려면 " 스윙 타이머 사용 방법 "을 찾아야합니다 .


6

내 코드는 다음과 같습니다.

new java.util.Timer().schedule(

    new java.util.TimerTask() {
        @Override
        public void run() {
            // your code here, and if you have to refresh UI put this code: 
           runOnUiThread(new   Runnable() {
                  public void run() {
                            //your code

                        }
                   });
        }
    }, 
    5000 
);

5

@tangens의 변형으로 가비지 수집기가 스레드를 정리할 때까지 기다릴 수 없으면 run 메소드 끝에서 타이머를 취소하십시오.

Timer t = new java.util.Timer();
t.schedule( 
        new java.util.TimerTask() {
            @Override
            public void run() {
                // your code here
                // close the thread
                t.cancel();
            }
        }, 
        5000 
);

내부 클래스 내에서 액세스 Timer t되므로 선언 해서는 final안됩니까?
Joshua Pinter

1
@JoshuaPinter 예, 최종 선언해야하지만 최소한 Java 8에서 최종적으로 명시 적으로 선언 할 필요는 없습니다. "효과적으로 최종" 이어야합니다 ( javarevisited.blogspot.com/2015/03/… )
Dandalf

4

원래 질문에는 "스윙 타이머"가 언급되어 있습니다. 실제로 질문이 SWing과 관련이 있다면 util.Timer가 아닌 Swing Timer를 사용해야합니다.

자세한 내용은 Swing 자습서에서 " 타이머 사용 방법 "섹션을 읽으십시오 .


4

Thread.Sleep () 함수를 사용할 수 있습니다

Thread.sleep(4000);
myfunction();

4 초 후에 기능이 실행됩니다. 그러나 이것은 전체 프로그램을 일시 중지시킬 수 있습니다 ...


또한 4 초 후에 실행이 실행되도록 보장합니다. 10 초 후에도 가능합니다!
questzen February

2
Questzen, 여기에 모든 방법이 있습니다. 실제로 OS 수준에서 일정을 예약하더라도 일반적으로 이벤트 전 최소 경과 시간 만 보장 할 수 있습니다.
Ethan

실제 질문이 아닙니다
Inder R Singh

나는 단지이 질문에 답을 주어야만했다.
마이어

OP는 논평에서 "나는 다른 일을 계속하고 싶다"고 말했다. 이 코드는 분명히 그렇지 않습니다.
Abhijit Sarkar

3

ScheduledThreadPoolExecutor 이 능력이 있지만 꽤 무겁습니다.

Timer 또한이 기능을 가지고 있지만 한 번만 사용하더라도 여러 스레드가 열립니다.

다음은 테스트를 사용한 간단한 구현입니다 (Android의 Handler.postDelayed ()에 가까운 서명 ).

public class JavaUtil {
    public static void postDelayed(final Runnable runnable, final long delayMillis) {
        final long requested = System.currentTimeMillis();
        new Thread(new Runnable() {
            @Override
            public void run() {
                // The while is just to ignore interruption.
                while (true) {
                    try {
                        long leftToSleep = requested + delayMillis - System.currentTimeMillis();
                        if (leftToSleep > 0) {
                            Thread.sleep(leftToSleep);
                        }
                        break;
                    } catch (InterruptedException ignored) {
                    }
                }
                runnable.run();
            }
        }).start();
    }
}

테스트:

@Test
public void testRunsOnlyOnce() throws InterruptedException {
    long delay = 100;
    int num = 0;
    final AtomicInteger numAtomic = new AtomicInteger(num);
    JavaUtil.postDelayed(new Runnable() {
        @Override
        public void run() {
            numAtomic.incrementAndGet();
        }
    }, delay);
    Assert.assertEquals(num, numAtomic.get());
    Thread.sleep(delay + 10);
    Assert.assertEquals(num + 1, numAtomic.get());
    Thread.sleep(delay * 2);
    Assert.assertEquals(num + 1, numAtomic.get());
}

그것은 루프에서 경고 수면을 제공합니다
shareef

while단지 중단을 무시하는 것이다.
AlikElzin-kilaka

2

다른 모든 unswer는 새 스레드 내에서 코드를 실행해야합니다. 일부 간단한 유스 케이스에서는 조금만 기다렸다가 동일한 스레드 / 흐름 내에서 실행을 계속할 수 있습니다.

아래 코드는 해당 기술을 보여줍니다. 이것은 java.util.Timer가 후드에서 수행하는 것과 유사하지만 더 가볍습니다.

import java.util.concurrent.TimeUnit;
public class DelaySample {
    public static void main(String[] args) {
       DelayUtil d = new DelayUtil();
       System.out.println("started:"+ new Date());
       d.delay(500);
       System.out.println("half second after:"+ new Date());
       d.delay(1, TimeUnit.MINUTES); 
       System.out.println("1 minute after:"+ new Date());
    }
}

DelayUtil 구현

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class DelayUtil {
    /** 
    *  Delays the current thread execution. 
    *  The thread loses ownership of any monitors. 
    *  Quits immediately if the thread is interrupted
    *  
    * @param duration the time duration in milliseconds
    */
   public void delay(final long durationInMillis) {
      delay(durationInMillis, TimeUnit.MILLISECONDS);
   }

   /** 
    * @param duration the time duration in the given {@code sourceUnit}
    * @param unit
    */
    public void delay(final long duration, final TimeUnit unit) {
        long currentTime = System.currentTimeMillis();
        long deadline = currentTime+unit.toMillis(duration);
        ReentrantLock lock = new ReentrantLock();
        Condition waitCondition = lock.newCondition();

        while ((deadline-currentTime)>0) {
            try {
                lock.lockInterruptibly();    
                waitCondition.await(deadline-currentTime, TimeUnit.MILLISECONDS);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return;
            } finally {
                lock.unlock();
            }
            currentTime = System.currentTimeMillis();
        }
    }
}

2
public static Timer t;

public synchronized void startPollingTimer() {
        if (t == null) {
            TimerTask task = new TimerTask() {
                @Override
                public void run() {
                   //Do your work
                }
            };

            t = new Timer();
            t.scheduleAtFixedRate(task, 0, 1000);
        }
    }

2
이 코드는 질문에 대답 할 수 있지만,이 코드가 질문에 응답하는 이유 및 / 또는 방법에 대한 추가 컨텍스트를 제공하면 장기적인 가치가 향상됩니다.
Mateus
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.