각 스레드에서 x
값을 보유 할 수 있도록 일부 공유 저장소를 만들거나 충분하면 합계를 저장하십시오. 스레드가 종료 될 때까지 대기하려면 CountDownLatch
을 사용하십시오. 작업이 끝나면 각 스레드는 CountDownLatch.countDown()
을 호출하고 myAlgorithm
메서드는 CountDownLatch.await()
메서드를 사용하여 스레드를 기다립니다.
편집 : 다음은 내가 제안한 접근 방식의 전체 예입니다. 39 개의 작업자 스레드가 생성되었으며 각 스레드는 공유 합계에 임의의 숫자를 추가합니다. 모든 근로자가 끝나면 평균이 계산되고 인쇄됩니다.
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
class Worker implements Runnable {
private final AtomicInteger sum;
private final CountDownLatch latch;
public Worker(AtomicInteger sum, CountDownLatch latch) {
this.sum = sum;
this.latch = latch;
}
@Override
public void run() {
Random random = new Random();
try {
// Sleep a random length of time from 5-10s
Thread.sleep(random.nextInt(5000) + 5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// Compute x
int x = random.nextInt(500);
// Add to the shared sum
System.out.println("Adding " + x + " to sum");
sum.addAndGet(x);
// This runnable is finished, so count down
latch.countDown();
}
}
class Program {
public static void main(String[] args) {
// There will be 39 workers
final int N = 39;
// Holds the sum of all results from all workers
AtomicInteger sum = new AtomicInteger();
// Tracks how many workers are still working
CountDownLatch latch = new CountDownLatch(N);
System.out.println("Starting " + N + " workers");
for (int i = 0; i < N; i++) {
// Each worker uses the shared atomic sum and countdown latch.
Worker worker = new Worker(sum, latch);
// Start the worker
new Thread(worker).start();
}
try {
// Important: waits for all workers to finish.
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
// Compute the average
double average = (double) sum.get()/(double) N;
System.out.println(" Sum: " + sum.get());
System.out.println("Workers: " + N);
System.out.println("Average: " + average);
}
}
출력 이런 식으로 뭔가해야한다 :
Starting 39 workers
Adding 94 to sum
Adding 86 to sum
Adding 454 to sum
...
...
...
Adding 358 to sum
Adding 134 to sum
Adding 482 to sum
Sum: 10133
Workers: 39
Average: 259.8205128205128
편집 : 그냥 재미를 위해, 여기 ExecutorService
, Callable
및 Future
를 사용하는 예입니다.
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledThreadPoolExecutor;
class Worker implements Callable<Integer> {
@Override
public Integer call() throws Exception {
Random random = new Random();
// Sleep a random length of time, from 5-10s
Thread.sleep(random.nextInt(5000) + 5000);
// Compute x
int x = random.nextInt(500);
System.out.println("Computed " + x);
return x;
}
}
public class Program {
public static void main(String[] args) {
// Thread pool size
final int POOL_SIZE = 10;
// There will be 39 workers
final int N = 39;
System.out.println("Starting " + N + " workers");
// Create the workers
Collection<Callable<Integer>> workers = new ArrayList<Callable<Integer>>(N);
for (int i = 0; i < N; i++) {
workers.add(new Worker());
}
// Create the executor service
ExecutorService executor = new ScheduledThreadPoolExecutor(POOL_SIZE);
// Execute all the workers, wait for the results
List<Future<Integer>> results = null;
try {
// Executes all tasks and waits for them to finish
results = executor.invokeAll(workers);
} catch (InterruptedException e) {
e.printStackTrace();
return;
}
// Compute the sum from the results
int sum = 0;
for (Future<Integer> future : results) {
try {
sum += future.get();
} catch (InterruptedException e) {
e.printStackTrace(); return;
} catch (ExecutionException e) {
e.printStackTrace(); return;
}
}
// Compute the average
double average = (double) sum/(double) N;
System.out.println(" Sum: " + sum);
System.out.println(" Workers: " + N);
System.out.println(" Average: " + average);
}
}
출력은 다음과 같아야합니다
Starting 39 workers
Computed 419
Computed 36
Computed 338
...
...
...
Computed 261
Computed 354
Computed 112
Sum: 9526
Workers: 39
Average: 244.25641025641025
놀라운! 나는 이것을 참고로 저장할 것입니다. 유전자 알고리즘을 코딩하여 테트리스 게임을하는 모든 에이전트는 서로 짝을 이루기 위해 게임을 마쳐야하므로 인구가 진화 할 수 있습니다. 각 게임은 다른 스레드에서 실행됩니다. 시간을내어 주시면 감사하겠습니다.이 java.util.concurrent API는 생명의 은인입니다! – Fernando
한 가지 더 궁금한 점이 있습니다 : 어떤 방법으로 CountDownLatch 나 ThreadedPool이 더 빠를 것입니까? 아니면 전혀 차이가 있습니까? 감사! – Fernando
제공된 예제에서 CountDownLatch가 빠릅니다. 그 이유는 CountDownLatch 예제에서 모든 스레드가 한 번에 생성되기 때문입니다. ExecutorService 예제에서, 내가 선택한'POOL_SIZE' 때문에 최대 10 개의 쓰레드가 동시에 실행될 수 있습니다. ExecutorService 예제에서'POOL_SIZE'를 39로 설정하면 결과는 CountDownLatch 예제와 거의 동일해야합니다. –