private CompletableFuture<Void> destroy() {
        assert handle != null : handle;
        return handle.closeAsync().handle((unused1, unused2) -> {
            lock.lock();
            try {
                if (destroyed) {
                    return null;
                }

                destroyed = true;

                // Cancel all scheduled tasks. Make a copy to prevent ConcurrentModificationException
                // when the future's handler removes it from scheduledFutures as a result of
                // the cancellation, which may happen on this thread.
                if (!scheduledFutures.isEmpty()) {
                    final ImmutableList<Future<?>> copy = ImmutableList.copyOf(scheduledFutures.keySet());
                    copy.forEach(f -> f.cancel(false));
                }
            } finally {
                lock.unlock();
            }

            endpointAttributes = healthCheckAttributes(false, false);
            onUpdateHealth.accept(originalEndpoint.withAttrs(endpointAttributes), false);

            return null;
        });
    }
Keeps the {@link Future}s which were scheduled via this {@link ScheduledExecutorService}.
Note that this field is also used as a lock.
core/src/main/java/com/linecorp/armeria/client/endpoint/healthcheck/DefaultHealthCheckerContext.java