Ответ 1
Прежде чем говорить что-либо о лямбда-выражениях или функциональных интерфейсах, мы должны поговорить о вашей действительно проблематичной ошибке: вы вызываете run()
в потоке! Если вы хотите запустить новый поток, вы должны вызвать start()
в экземпляре Thread
, если вы хотите последовательно запускать код, не создавайте Thread
(но просто Runnable
).
Тем не менее, существует несколько методов default
на функциональных интерфейсах Java 8 для объединения функций, например. вы можете связать два Function
с помощью Function.andThen(…)
, но доступные комбинации далеки от завершения.
Если некоторая комбинирующая задача повторяется в вашем приложении, вы можете подумать о создании методов утилиты:
public static <T> Runnable bind(T value, Consumer<T> c) {
return ()->c.accept(value);
}
public static <T,U> Consumer<U> compose(Function<U,T> f, Consumer<? super T> c) {
return u->c.accept(f.apply(u));
}
new Thread(bind("Hello 1", compose(upper, d))).start();
new Thread(bind("Hello 2", compose(lower, d))).start();
Но эти три части больше напоминают задачу для API потока:
Stream.of("Hello 1").map(upper).forEach(d);
Stream.of("Hello 2").map(lower).forEach(d);
Я оставил здесь создание нового потока, так как он все равно не имеет никакой пользы.
Если вам действительно нужна параллельная обработка, вы можете сделать это на основе символов:
"Hello 1".chars().parallel()
.map(Character::toUpperCase).forEachOrdered(c->System.out.print((char)c));
но все равно не будет никакой выгоды, учитывая простоту задачи и фиксированные накладные расходы на параллельную обработку.