Строки соответствуют требуемым в условии, но проверку форматирования не проходят. Пробовал по-разному, в итоге пока так. 1. getPartOfString:
public synchronized String getPartOfString(String string, String threadName) {
    String res = "";
    try {
        res = string.substring(string.indexOf("\t") + 1, string.lastIndexOf("\t"));
    } catch (Exception e) {
        if (threadName.equals(FIRST_THREAD_NAME))
            throw new StringForFirstThreadTooShortException(e);
        if (threadName.equals(SECOND_THREAD_NAME))
            throw new StringForSecondThreadTooShortException(e);
        throw new RuntimeException(e);
    }

    return res;
}
2. Переопределили эксепшены
public class StringForFirstThreadTooShortException extends RuntimeException {
    public StringForFirstThreadTooShortException(Throwable cause) {
        super(cause);
    }
}
public class StringForSecondThreadTooShortException extends RuntimeException {
    public StringForSecondThreadTooShortException(Throwable cause) {
        super(cause);
    }
}
3. Само форматирование:
public class OurUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
    @Override
    public void uncaughtException(Thread t, Throwable e) {
        final String string = "%s : %s : %s";
        if (Solution.FIRST_THREAD_NAME.equals(t.getName())) {
            System.out.println(getFormattedStringForFirstThread(t, e, string));
        } else
            if (Solution.SECOND_THREAD_NAME.equals(t.getName())) {
                System.out.println(getFormattedStringForSecondThread(t, e, string));
            } else {
                System.out.println(getFormattedStringForOtherThread(t, e, string));
            }
    }

    protected String getFormattedStringForOtherThread(Thread t, Throwable e, String string) {
        return String.format(string, "RuntimeException", e.getCause(), t.getName());
    }

    protected String getFormattedStringForSecondThread(Thread t, Throwable e, String string) {
        return String.format(string, e.getCause(), "StringForSecondThreadTooShortException", t.getName());
    }

    protected String getFormattedStringForFirstThread(Thread t, Throwable e, String string) {
        return String.format(string, t.getName(), "StringForFirstThreadTooShortException", e.getCause());
    }
}
Запуск на дефолтных примерах: 3# 3# 2#J K L M N O P Q R S T U V W X Y Z 1#A B C D E F G H I 1#B C D E F G H 2#K L M N O P Q R S T U V W X Y 2#L M N O P Q R S T U V W X 2#M N O P Q R S T U V W 2#N O P Q R S T U V 2#O P Q R S T U 2#P Q R S T 2#Q R S 2#R 1#C D E F G 1#D E F 1#E 1# : StringForFirstThreadTooShortException : java.lang.StringIndexOutOfBoundsException: String index out of range: -1 java.lang.StringIndexOutOfBoundsException: String index out of range: -1 : StringForSecondThreadTooShortException : 2# RuntimeException : java.lang.StringIndexOutOfBoundsException: String index out of range: -1 : 3#