@Override
    public void run() {
        while (!stopped) {
            Set<Long> mappedIds;
            synchronized (threadTimeMap) {
                mappedIds = new HashSet<>(threadTimeMap.keySet());
            }

            long[] allThreadIds = threadBean.getAllThreadIds();

            if (mappedIds != null) {
                removeDeadThreads(mappedIds, allThreadIds);
            }

            if (allThreadIds != null) {
                mapNewThreads(allThreadIds);
            }

            Collection<ThreadTime> values;
            synchronized (threadTimeMap) {
                values = new HashSet<>(threadTimeMap.values());
            }

            for (ThreadTime threadTime : values) {
                synchronized (threadTime) {
                    threadTime.setCurrent(threadBean.getThreadCpuTime(threadTime.getId()));
                }
            }
            maxMemory = runtime.maxMemory();
            totalMemory = runtime.totalMemory();
            freeMemory = runtime.freeMemory();

            try {
                Thread.sleep(refreshInterval);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

            for (ThreadTime threadTime : values) {
                synchronized (threadTime) {
                    threadTime.setLast(threadTime.getCurrent());
                }
            }
        }
    }