code: public static Collection<Thread> findThreads(final ThreadGroup group, final boolean recurse, final ThreadPredicate predicate) {
          Validate.isTrue(group != null, "The group must not be null");
          Validate.isTrue(predicate != null, "The predicate must not be null");
  
          int count = group.activeCount();
          Thread[] threads;
          do {
              threads = new Thread[count + (count / 2) + 1]; //slightly grow the array size
              count = group.enumerate(threads, recurse);
              //return value of enumerate() must be strictly less than the array size according to javadoc
          } while (count >= threads.length);
  
          final List<Thread> result = new ArrayList<>(count);
          for (int i = 0; i < count; ++i) {
              if (predicate.test(threads[i])) {
                  result.add(threads[i]);
              }
          }
          return Collections.unmodifiableCollection(result);
      }
docs: Select all active threads which match the given predicate and which belongs to the given thread group (or one of its subgroups).
  
  @param group the thread group
  @param recurse if {@code true} then evaluate the predicate recursively on all threads in all subgroups of the given group
  @param predicate the predicate
  @return An unmodifiable {@code Collection} of active threads which match the given predicate and which belongs to the given thread group
  @throws IllegalArgumentException if the given group or predicate is null
  @throws  SecurityException  if the current thread cannot modify
  thread groups from this thread's thread group up to the system thread group