public class TcpServer implements ApplicationContextAware{ private OpenbankExecutor executor; private int port; private PacketHandler packetHandler; private ServerSocket serverSocket; private Socket socket; private ApplicationContext applicationContext; private final Logger log = LoggerFactory.getLogger(getClass()); public void init() throws IOException { serverSocket = new ServerSocket(port); log.debug("TcpServer 成功启动"); while(true) { socket = serverSocket.accept(); System.out.println("收到socket请求"); executor.execute(new Runnable() { @Override public void run() { try { Map context = packetHandler.handle(socket.getInputStream()); String tranCode = (String) context.get("tranCode"); Assert.hasText(tranCode); Transaction transaction = (Transaction) applicationContext.getBean(tranCode); Template template = (Template) applicationContext.getBean(transaction.getTemplate()); log.debug("transaction: "+transaction.getId()); log.debug("transaction: "+template.getId()); } catch (Exception e) { e.printStackTrace(); } } }); } }
走到Transaction transaction = (Transaction) applicationContext.getBean(tranCode);就没有往下走了,没有报错。非多线程方式下这个方法是没有问题的,比如我将这一段放到executor.execute(new Runnable() {之前就没有问题,求解
不太懂,多线程才有问题会不会是哪儿死锁了
不清楚原因,我重新写了一个简单的多线程场景的测试并没有复现这个问题,等我搞清楚原因再来结贴
前段时间在准备面试,所以这时候才来结贴,唉面试失败了
搞懂了,是这样的:TcpServer这个类是我通过spring ioc配置的bean:
<bean id="tcpServer" class="com.openbank.portal.server.TcpServer" init-method="init">
略
</bean>
spring在加载这个类的时候,就使用init方法来初始化,结果我里面启了一个serversocket并且进入了serverSocket.accept()方法,结果就在这里阻塞了spring继续实例化剩下还没有来得及实例的bean。
我改了一下,serverSocket.accept()之前,我起了一个新的线程来做这件事情,就不会有这个问题了。
我debug了一下spring的源代码,卡在了一个synchronized方法,一直没有拿到锁。反正大概意思就是这样的。
@捡肉王:
哦,所以是因为serverSocket.accept()一直处于等待状态,导致锁没有释放吗?
@苍枫露雨: 嗯哼 我是这样认为的