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