Call Interrupt на потоке работает очень медленно - PullRequest
0 голосов
/ 28 октября 2019

У меня есть одна ConcurrentHashMap, где я храню потоки, которые отправляют некоторые данные в сокет и ожидают ответа.

public class MyThreadSocketAsync implements Runnable

Внутри этого потока у меня есть:

// add to hashmap
SocketHandler.getInstance().addThread(this, Thread.currentThread());

// send data
this.sendData();
 log.info("goToSleep");

//go to sleep
try {
    Thread.sleep(5000);
} catch (Exception t) {
}
log.info ("Thread awaken");

где в SocketHandlerУ меня есть:

public void addThread(MyThreadSocketAsync t, Thread thread) {
    String threadIdS = generateThreadKey(t.getThreadId());
    threadList.put(threadIdS, new Object[] { t, thread });
}

Теперь у меня есть другой поток, который читает некоторые данные из сокета и решает, какой поток должен проснуться, основываясь на уникальном идентификаторе потока.

public void releaseThread(String threadId, String returnValue) {
  Object[] o = threadList.remove(threadId);
  MyThreadSocketAsync t = o != null ? (MyThreadSocketAsync) o[0] : null;
  if (t != null) {
    t.setReturnValue(returnValue, threadId);
    ((Thread) o[1]).interrupt();
     log.info ("Awake thread");
  }
}

Проблема заключается в том, что между двумя журналами "«Пробудить нить» и «Пробудить нить» через некоторое время у меня более 5 - 20 секунд. Кажется, что когда я выполняю прерывание в потоке, оно не выполняется сразу. Теперь важно, чтобы это происходило время от времени (особенно, когда в системе выполняется более одного параллельного потока). Вопрос в том, почему иногда прерывания не работают сразу?

Журнал с рабочего сервера:

25.10.2019 13:29:30.207  [DEBUG]  163133 > logMemoryUsageInfo : Total memory used: 23877 KB, free memory:37562 KB, JVM threadCount:17
25.10.2019 13:29:30.207  [INFO ]  163133 > MyThreadSocketAsync.run : Message received, concurentThreads:5
25.10.2019 13:29:30.211  [INFO ]  163133 > MyThreadSocketAsync.handleMessage : length:40, hex:08008220000****
25.10.2019 13:29:30.211  [INFO ]  163133 > MyThreadSocketAsync.handleMessage : ECHO message received
25.10.2019 13:29:30.211  [INFO ]  163133 > SocketHandler.addThread : key=0000163133, threadList.size=8
25.10.2019 13:29:30.211  [INFO ]  163133 > SocketHandler.sendMessage : messageToSend=0000163133101****
25.10.2019 13:29:30.211  [DEBUG]  163133 > MyThreadSocketAsync.handleMessage : goToSleep
25.10.2019 13:29:30.258  [INFO ]  163133 > SocketHandler.releaseThread : Awake thread key=0000163133, threadList.size=12
25.10.2019 13:30:32.304  [DEBUG]  163133 > MyThreadSocketAsync.handleMessage : Thread Awaken=62093 msec
25.10.2019 13:30:32.305  [DEBUG]  163133 > MyThreadSocketAsync.handleMessage : Exit thread

Также существует другое странное поведение, которое может быть связано с этим.

Есть также ситуации, когда Thread пробуждается через 20 мсек, но не с моим методом interrupt (), а с чем-то другим (системным, GC, ..) потоком прерываний, поэтому в моем журнале есть только:

25.10.2019 13:24:57.011  [DEBUG]  162448 > MyThreadSocketAsync.handleMessage : goToSleep
25.10.2019 13:24:57.026  [DEBUG]  162448 > MyThreadSocketAsync.handleMessage : Thread Awaken=15 msec

Понятия не имею, почему это происходит время от времени?

Для выполнения потоков я использую threadPool:

threadPool = new ThreadPoolExecutor(10, 500, 1800, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
...
MyThreadSocketAsync cc = new MyThreadSocketAsync(messageCount, receivedMessage);
threadPool.execute(cc);
...