Przy wielu wątkach lepiej użyć ExecutorService, ale trzeba wtedy pamiętać o jego zamknięciu gdy nie jest już potrzebny:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Main {
private static final int NUMBER_OF_TASKS = 4;
public static void main(String[] args) {
AtomicInteger threadCounter = new AtomicInteger(1);
ExecutorService executor = Executors.newFixedThreadPool(
NUMBER_OF_TASKS,
runnable -> new Thread(runnable, "WorkerThread-" + threadCounter.getAndIncrement())
);
try {
Stream.<Runnable>generate(() -> Main::doSomeWork)
.limit(NUMBER_OF_TASKS)
.map(executor::submit)
.collect(Collectors.toList())
.forEach(future -> {
try {
future.get();
} catch (Exception ex) {
ex.printStackTrace();
}
});
} finally {
executor.shutdown();
}
}
private static void doSomeWork() {
System.out.println("Doing some work in thread: " + Thread.currentThread().getName());
try {
Thread.sleep(ThreadLocalRandom.current().nextInt(5000));
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
System.out.println("Work done in thread: " + Thread.currentThread().getName());
}
}
Można też użyć wbudowanego ForkJoinPool i parallel streama:
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.IntStream;
public class Main {
private static final int NUMBER_OF_TASKS = 4;
public static void main(String[] args) {
IntStream.range(0, NUMBER_OF_TASKS)
.parallel()
.<Runnable>mapToObj(i -> Main::doSomeWork)
.forEach(Runnable::run);
}
private static void doSomeWork() {
System.out.println("Doing some work in thread: " + Thread.currentThread().getName());
try {
Thread.sleep(ThreadLocalRandom.current().nextInt(5000));
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
System.out.println("Work done in thread: " + Thread.currentThread().getName());
}
}