public synchronized void checkThread(Callable workToDo, Callable callback, Integer limitRate) throws DropCountExceededException {

        if (workToDo != null) {
            try {
                this.checkThread(null, callback, null);

                workToDo.call();

                this.releaseThread();
            } catch (Exception e) {
                throw new DropCountExceededException(e);
            }
        } else {

            Method callingMethod = queryCallingMethod();

            LOGGER.debug("method = {} : {}", callingMethod, channelCount.containsKey(callingMethod));

            Integer localLimitRate;

            if (callingMethod.getAnnotation(LimitRate.class) != null) {
                localLimitRate = callingMethod.getAnnotation(LimitRate.class).value();
            } else {
                if (callingMethod.getAnnotation(LimitRateProperty.class) != null) {
                    String propertyName = callingMethod.getAnnotation(LimitRateProperty.class).name();

                    localLimitRate = Integer.parseInt(System.getProperty(propertyName));
                } else {
                    localLimitRate = limitRate;
                }
            }

            if (localLimitRate == null) {
                throw new DropCountExceededException("Could not evaluate LimitRate value!");
            }

            if (channelCount.containsKey(callingMethod)) {
                if (channelCount.get(callingMethod).getMaxCount() != localLimitRate) {
                    channelCount.remove(callingMethod);
                    channelCount.put(callingMethod, new VO(localLimitRate));
                }
            } else {
                channelCount.put(callingMethod, new VO(localLimitRate));
            }

            LOGGER.debug("[{}] maxCount:{}", callingMethod, channelCount.get(callingMethod).getMaxCount());
            LOGGER.debug("[{}] threadCount:{}", callingMethod, channelCount.get(callingMethod).getThreadCount());

            if (channelCount.get(callingMethod).getThreadCount().get() < channelCount.get(callingMethod).getMaxCount()) {
                channelCount.get(callingMethod).getThreadCount().incrementAndGet();
            } else {
                if (callback == null) {
                    throw new DropCountExceededException();
                } else {
                    callback.call();
                }
            }
        }
    }