// assumes that each set function is called exactly once // (but it doesn't matter which thread you call each of them from.) sclass LongPairCollector > AtomicCounter { volatile long valueOfA; volatile long valueOfB; final LongConsumer a = l1 setA; final LongConsumer b = l1 setB; void setA(long a) { valueOfA = a; itemReceived(); } void setB(long b) { valueOfB = b; itemReceived(); } LongConsumer setA aka setterForA() { ret a; } LongConsumer setB aka setterForB() { ret b; } void itemReceived { if (incCounter() == 2) complete(valueOfA, valueOfB); } // override me void complete(long a, long b) {} }