Вы не можете сделать это поточно-ориентированным, но вы можете синхронизировать доступ к библиотеке:
static Object globalLock = new Object();
synchronize (globalLock) {
evaluate();
}
Это означает, конечно, что только один поток может выполнять этот метод одновременно. Так что если ваша программа тратит много времени на этот метод, это вам не поможет.
Кроме того, вы можете запустить экземпляры в отдельных процессах. Но установление связи между процессами (через RMI или подобное) довольно болезненно.
Единственный другой вариант - переписать его, если вы обращаетесь к исходному коду. Вам нужно переместить все статические поля в один класс контекста, а затем убедиться, что весь код, который использовался для доступа к статическим полям, имеет ссылку на экземпляр нового класса контекста.
Уже упомянутый механизм ThreadLocal может помочь вам в этом, потому что это особый вид ссылок, который выглядит по-разному для каждого потока. Это может избавить вас от изменения сигнатур методов для передачи экземпляра объекту контекста. ИМХО, наверное, понятнее просто передать контекст в методы. С функциями рефакторинга современных IDE это не так сложно сделать.