Is there a way to run getUsers()
asynchronously only from main()
in Java 8?
Running getUsers()
on the main thread would take 300 seconds. I wish to make it in less than 180 seconds with 4 cores.
public class Main { // Getting users (with sleep) public List<User> getUsers() { List<User> users = new ArrayList(); for(int i = 0; i < 100; i++) { users.add(new User("someName", "someAge")); TimeUnit.MILLISECONDS.sleep(3000); } return users; } public static void main(String[] args) { List<User> users = getUsers(); } }
Without modifying getUsers()
(the objective), running the following is still taking 300 seconds:
public static void main(String[] args) { List<User> users = CompletableFuture.supplyAsync(() -> getUsers()).join(); }
Advertisement
Answer
You can divide your loop of users creation into smaller loops, and run them in parallel. Consider this example, which runs 4 times faster :
public static void main(String[] args) { // create a pool executor of 4 threads, increase or decrease it if need Executor executor = Executors.newFixedThreadPool(4); CompletableFuture<List<User>> future1 = CompletableFuture.supplyAsync(() -> getUsers(25), executor); CompletableFuture<List<User>> future2 = CompletableFuture.supplyAsync(() -> getUsers(25), executor); CompletableFuture<List<User>> future3 = CompletableFuture.supplyAsync(() -> getUsers(25), executor); CompletableFuture<List<User>> future4 = CompletableFuture.supplyAsync(() -> getUsers(25), executor); List<User> allUsers = Stream.of(future1, future2, future3, future4) .map(CompletableFuture::join) .flatMap(List::stream) .collect(Collectors.toList()); } public static List<User> getUsers(int count) { List<User> users = new ArrayList<>(); for (int i = 0; i < count; i++) { users.add(new User("someName", "someAge")); try { TimeUnit.MILLISECONDS.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } } return users; }