Это может определенно вызвать случайные сбои. В вашем процессе будет только один экземпляр статического ресурса. Это означает, что каждый поток, который пытается получить доступ к этим статическим ресурсам, может оказаться в ситуации, когда другой поток пытается получить доступ к тем же статическим ресурсам.
Давайте рассмотрим пример вашей функции :: assertResult. Эта функция может быть доступна двум потокам одновременно с разными значениями «фактических» и «ожидаемых» параметров. Поскольку assertTrue не является атомарной операцией, значения данных (фактические и ожидаемые) могут смешиваться между двумя потоками. Это может привести к неожиданным результатам для вас. Я бы порекомендовал вам лучший дизайн с поддержкой многопоточности, но чтобы быстро решить эту проблему, вы можете использовать синхронизированное ключевое слово в определении функций всех методов, к которым могут обращаться несколько потоков одновременно.
public synchronized static void assertResult(String actual, String expected) {
assertTrue(actual.contains(expected),
"FAILED : Actual : " + actual + " Expected : " + expected,
"PASSED : Actual : " + actual + " Expected : " + expected);
}
Хотя есть и лучшие решения, чем добавление синхронизированного ключевого слова, которое должно появиться в вашем упражнении по редизайну. В этом случае одной из видимых проблем добавления синхронизированного ключевого слова будет увеличение времени выполнения на незначительный фактор. Это связано с тем, что несколько потоков начнут ожидать других потоков при попытке доступа к синхронизированному методу.