package ex2; import java.util.HashMap; import java.util.Map; import java.util.concurrent.atomic.LongAdder; public final class Profiler { // not concurrent on purpose, since the value of the map is computed with a pure function // on the map key, and thus we don't care if the value is overwritten as a result of a // race condition private static final Map, Boolean> isThread = new HashMap<>(); private static final LongAdder reads = new LongAdder(); private static final LongAdder writes = new LongAdder(); static { Runtime.getRuntime().addShutdownHook(new Thread(() -> { System.out.printf("Instance field read access: %d\nInstance field write access: %d\n", reads.longValue(), writes.longValue()); })); } private Profiler() { } public static boolean isThread(final Class clazz) { return isThread.computeIfAbsent(clazz, Thread.class::isAssignableFrom); } public static void increment(long readCount, long writeCount) { reads.add(readCount); writes.add(writeCount); } }