Java tutorial
import java.util.ArrayList; import java.util.List; import java.util.Random; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class Main { static Random rand = new Random(); static final Lock lock = new ReentrantLock(); static boolean updating = false; static List<Future<Integer>> futureList = new ArrayList<Future<Integer>>(); static ExecutorService pool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); static Callable<Integer> callable = new Callable<Integer>() { @Override public Integer call() { return rand.nextInt(); } }; static void doUpdate() { if (lock.tryLock()) { updating = true; try { for (Future<Integer> future : futureList) { System.out.println(future.get()); } futureList.clear(); } catch (Exception e) { e.printStackTrace(); } finally { System.out.println(); lock.unlock(); updating = false; } } } public static void main(String[] args) throws Exception { new Thread(() -> { int submitCount = 0; while (submitCount < 10) { if (!updating) { futureList.add(pool.submit(callable)); submitCount++; } try { Thread.sleep(1000); // arbitrary } catch (Exception e) { e.printStackTrace(); } } }).start(); // update thread new Thread(() -> { int updateCount = 0; while (updateCount < 5) { doUpdate(); updateCount++; try { Thread.sleep(2000); } catch (Exception e) { e.printStackTrace(); } } }).start(); } }