+ /**
+ * Build the thread attribute name.
+ *
+ * For all threads except "0" this is the string representation of the threadId.
+ * For thread "0" which is the idle thread and can be running concurrently on multiple
+ * CPUs, append "_cpuId".
+ *
+ * @param threadId
+ * the thread id
+ * @param cpuId
+ * the cpu id
+ *
+ * @return the thread attribute name
+ * null if the threadId is zero and the cpuId is null
+ */
+ public static @Nullable String buildThreadAttributeName(int threadId, @Nullable Integer cpuId) {
+
+ if (threadId == 0) {
+ if (cpuId == null) {
+ return null;
+ }
+ return Attributes.THREAD_0_PREFIX + String.valueOf(cpuId);
+ }
+
+ return String.valueOf(threadId);
+ }
+
+ /**
+ * Parse the thread id and CPU id from the thread attribute name string
+ *
+ * For thread "0" the attribute name is in the form "threadId_cpuId", extract both
+ * values from the string.
+ *
+ * For all other threads, the attribute name is the string representation of the
+ * threadId and there is no cpuId.
+ *
+ * @param threadAttributeName
+ * the thread attribute name
+ * @return the thread id and cpu id
+ */
+ public static Pair<Integer, Integer> parseThreadAttributeName(String threadAttributeName) {
+ Integer threadId = -1;
+ Integer cpuId = -1;
+
+ try {
+ if (threadAttributeName.startsWith(Attributes.THREAD_0_PREFIX)) {
+ threadId = 0;
+ String[] tokens = threadAttributeName.split(Attributes.THREAD_0_SEPARATOR);
+ cpuId = Integer.parseInt(tokens[1]);
+ } else {
+ threadId = Integer.parseInt(threadAttributeName);
+ }
+ } catch (NumberFormatException e1) {
+ //pass
+ }
+
+ return new Pair<>(threadId, cpuId);
+ }