3 개의 스레드가 동시에 작업을 수행하고 일정 기간 (10 초마다 실행 됨)에 예약 된 작업을 수행하는 스레드가 필요합니다. 하지만 3 스레드가 예약 된 작업을 한 번만 실행하고이 스레드가 종료되도록하고 싶을 때가 있습니다. 이 스레드를 구현하는 가장 좋은 방법은 무엇입니까? ExecutorService 인터페이스는 이에 적합합니다. 여기다른 스레드가 완료된 후 주기적 작업 일정 예약
0
A
답변
3
난 그냥 작성한 것으로 예 : 여기
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
public class Example {
public static void main(String[] args) throws InterruptedException {
ScheduledFuture future = Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new MyScheduledTask(), 0, 10, TimeUnit.SECONDS);
ExecutorService executor = Executors.newFixedThreadPool(3); // pool composed of 3 threads
for (int i = 0; i < 3; i++) {
// for the example assuming that the 3 threads execute the same task.
executor.execute(new AnyTask());
}
// This will make the executor accept no new threads
// and finish all existing threads in the queue
executor.shutdown();
// expect current thread to wait for the ending of the 3 threads
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.TimeUnit.NANOSECONDS);
future.cancel(false); // to exit properly the scheduled task
// reprocessing the scheduled task only one time as expected
new Thread(new ScheduledTask()).start();
}
}
class MyScheduledTask implements Runnable {
@Override
public void run() {
//Process scheduled task here
}
}
class AnyTask implements Runnable {
@Override
public void run() {
//Process job of threads here
}
}
1
는 작업을 하나씩 실행하는주기적인 작업 스케줄러의 예입니다. 작업 스케줄러는 작업 배열을 가져 와서 별도의 스레드에서 지정된 간격 후에 각 작업을 종료합니다. 20 초 후에 주 스레드는 스케줄러를 종료하고 대기중인 모든 작업을 중지합니다.
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
public class Example {
class ScheduledRepeatingTask implements Runnable {
final ScheduledExecutorService scheduler = Executors
.newScheduledThreadPool(1);
List<Runnable> taskCollection;
Iterator<Runnable> taskIterator;
Runnable getCancelRunnable(final ScheduledFuture<?> future) {
Runnable cancelFuture = new Runnable() {
public void run() {
future.cancel(true);
}
};
return cancelFuture;
}
public ScheduledRepeatingTask(Runnable[] tasks) {
super();
taskCollection = Arrays.asList(tasks);
taskIterator = taskCollection.iterator();
}
public void shutdownScheduler() throws InterruptedException {
scheduler.shutdown();
boolean execTerminated = scheduler.awaitTermination(5,
TimeUnit.SECONDS);
if (!execTerminated) {
scheduler.shutdownNow();
}
}
public boolean isShutdown(){
return scheduler.isShutdown();
}
public void scheduleRepeatingTask(ScheduledFuture<?> future,
ScheduledFuture<?> futureCancel) {
try {
futureCancel.get();
future.get();
} catch (CancellationException e) {
System.out.println("cancelled.");
} catch (ExecutionException e) {
Throwable exp = e.getCause();
if (exp instanceof RuntimeException) {
System.out.println("failed.");
RuntimeException rt = (RuntimeException) exp;
throw rt;
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
if (!scheduler.isShutdown() && taskIterator.hasNext()) {
future = scheduler.scheduleAtFixedRate(taskIterator.next(),
2, 2, TimeUnit.SECONDS);
futureCancel = scheduler.schedule(
getCancelRunnable(future), 5, TimeUnit.SECONDS);
scheduleRepeatingTask(future, futureCancel);
}
}
}
@Override
public void run() {
if (!scheduler.isShutdown() && taskIterator.hasNext()) {
ScheduledFuture<?> future = scheduler.scheduleAtFixedRate(
taskIterator.next(), 2, 2, TimeUnit.SECONDS);
ScheduledFuture<?> futureCancel = scheduler.schedule(
getCancelRunnable(future), 5, TimeUnit.SECONDS);
scheduleRepeatingTask(future, futureCancel);
}
}
}
public static void main(String[] args) throws InterruptedException {
Example example = new Example();
ExecutorService executor = Executors.newCachedThreadPool();
Runnable[] tasks = { new Task1(), new Task2(), new Task1() };
ScheduledRepeatingTask scheduledRepeatingTask = example.new ScheduledRepeatingTask(tasks);
executor.execute(scheduledRepeatingTask);
Thread.sleep(20000);
scheduledRepeatingTask.shutdownScheduler();
executor.shutdown();
}
}
class Task1 implements Runnable {
@Override
public void run() {
System.out.println("Task 1");
}
}
class Task2 implements Runnable {
@Override
public void run() {
System.out.println("Task 2");
}
}
작동합니다. 사실 내 솔루션의 문제점은'sheduler.shutdown()'을'executor.aWaitTermination()'의 try 블록 안에 넣었다는 것입니다. ScheduledExecutorService를 사용하여 스케줄러를 생성했습니다. 그 해결책에 대해 어떻게 생각하세요? – Manos
@Manos Samatas 흠, 게시물을 업데이트하여 코드를 표시 할 수 있습니까? – Mik378
@Manos Samatas 어쨌든'executor.aWaitTermination()'은 논리적으로'sheduler.shutdown()'뒤에 있어야합니다. 그렇지 않으면 현재 스레드가 최대 시간 동안 대기 한 다음 풀이 종료됩니다 ... 공연. 게다가, 현재 쓰레드가 다른 쓰레드의 종료를 기다리기 전에 그 쓰레드를 계속해서 수행하지 못하게하는 것은 아무것도 없다. – Mik378