// 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 a; volatile long b; void setA(long a) { this.a = a; itemReceived(); } void setB(long b) { this.b = b; itemReceived(); } LongConsumer setA aka setterForA() { ret a -> setA(a); } LongConsumer setB aka setterForB() { ret b -> setB(b); } void itemReceived { if (incCounter() == 2) complete(a, b); } // can override or swap swappable void complete(long a, long b) {} }