Сделка переменного ожидания
Я использую jboss 5.1.x, EJB3.0
У меня есть MDB, который слушает очередь JMS. когда MDB принимает сообщение, он отправляет msg через TCP на какой-то модем. иногда этот модем не отвечает, когда сервер ждет ответа:
byte[] byteData = receive(is);
потому что я не могу установить тайм-аут на InputStream.
таким образом, благодаря контейнеру EJB тайм-аут транзакции (который есть по умолчанию) откат операции, а затем повторная попытка выполнена снова.
этот механизм по умолчанию отлично работает для меня, проблема:
иногда транзакция никогда не истекала, и после долгого времени я получаю следующее сообщение в консоли:
15:18:22,578 WARN [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.TransactionReaper_18] - TransactionReaper::check timeout for TX a6b2232:5f8:4d3591c6:76 in state RUN
15:18:22,578 WARN [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.BasicAction_58] - Abort of action id a6b2232:5f8:4d3591c6:76 invoked while multiple threads active within it.
15:18:22,578 WARN [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.CheckedAction_2] - CheckedAction::check - atomic action a6b2232:5f8:4d3591c6:76 aborting with 1 threads active!
15:18:22,578 WARN [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.TransactionReaper_7] - TransactionReaper::doCancellations worker Thread[Thread-10,5,jboss] successfully canceled TX a6b2232:5f8:4d3591c6:76
есть идеи, что случилось? и почему иногда это работает, а иногда нет?
спасибо,
Рэй.
1 ответов
JBossAS, который использует менеджер транзакций Арджуны. В ejb3 цепочка перехватчиков начнет разворачиваться и в конечном итоге попадет в перехватчики диспетчера транзакций, чья задача-прервать транзакцию.
для MDB вы можете annote его с
@ActivationConfigProperty(propertyName="transactionTimeout" value="1500")
для других бобов вы можете иметь
@TransactionTimeout(1500)
на уровне класса или метода.
когда диспетчер транзакций обнаруживает, что время ожидания транзакции истекло и затем прерывает его из асинхронного потока (отличного от потока, работающего в методе), но он никогда не отправляет прерывание в текущий поток.
в результате : вызывается в то время как несколько потоков активны в нем ... прерывание с активными потоками 1!Edit:
//---
ThreadGroup root = Thread.currentThread().getThreadGroup().getParent();
while (root.getParent() != null)
root = root.getParent();
findAllThread(root,0);
//---
public static findAllThread(ThreadGroup threadGroup, int level){
int actCount = threadGroup.activeCount();
Thread[] threads = new Thread[actCount*2];
actCount = threadGroup.enumerate(threads, false);
for (int i=0; i<actCount; i++) {
Thread thread = threads[i];
thread.interrupt();
}
int groupCount = threadGroup.activeGroupCount();
ThreadGroup[] groups = new ThreadGroup[numGroups*2];
groupCount = threadGroup.enumerate(groups, false);
for (int i=0; i<groupCount; i++)
findAllThread(groups[i], level+1);
//---
он будет перечислять другие активные потоки, такие как обработчик ссылок, финализатор, диспетчер сигналов и т. д.