держать linkedhashset<userid> (просто покрытый локом; нужно что-то с порядком + уникальностью э-тов) свободных userid, у которых есть невыполненные задачи, + CHM<userid, blockingqueue<task>>, как чуть выше написано
тред выполнил 1 задачу для конкретного userid? проверяет есть ли ещё задачи (только он сейчас владеет userid, поэтому это безопасно) - если есть ещё, добавляет в конец blockingqueue
если приходит задача извне, тред добавляет в linkedhashset (не обновляя порядок) + в соотв. очередь складывает задачу (тут может быть ситуация что внешний тред лезет в конкретный userid и какой-то воркер владеет этим userid - поэтому стоит поддерживать уникальность на уровне списка свободных userid)