private String generateName(Handler handler) {
        Map<Class<?>, String> cache = nameCaches.get();
        Class<?> handlerType = handler.getClass();
        String name = cache.get(handlerType);
        if (name == null) {
            name = generateName0(handlerType);
            cache.put(handlerType, name);
        }

        synchronized (this) {
            // It's not very likely for a user to put more than one handler of the same type, but make sure to avoid
            // any name conflicts.  Note that we don't cache the names generated here.
            if (context0(name) != null) {
                String baseName = name.substring(0, name.length() - 1); // Strip the trailing '0'.
                for (int i = 1;; i ++) {
                    String newName = baseName + i;
                    if (context0(newName) == null) {
                        name = newName;
                        break;
                    }
                }
            }
        }

        return name;
    }
Most of the code references the pipeline design of
<a href="https://github.com/netty/netty">Netty</a>.

@author jiachun.fjc
jraft-rheakv/rheakv-core/src/main/java/com/alipay/sofa/jraft/rhea/util/pipeline/DefaultPipeline.java