我有一个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 });
}
现在,我有另一个线程从套接字读取一些数据,并根据唯一的threadId决定应唤醒哪个线程。
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
还有另一种奇怪的行为,可能与此有关。
在某些情况下,线程会在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);