【发布时间】:2016-05-31 05:19:15
【问题描述】:
我在 Java 中创建了 Glassfish 4.0 服务器,但在我的 ArrayList<> 上遇到了一个奇怪的错误。这是我的init() 代码:
@Override
public void contextInitialized(ServletContextEvent arg0) {
init();
}
private void init() {
sessions = new ArrayList<Session>();
new Thread(new Runnable() {
@Override
public void run() {
synchronized(sessions){
while(sessions.size() == 0){
try {
Thread.sleep(1000);
System.out.println("No sessions available: " + sessions);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
本质上,当服务器启动时,会话ArrayList 被实例化,一个新的线程开始循环等待 WebSocket 连接发生。下面是 WebSocket 连接的代码:
@OnOpen
public void open(Session session) {
System.out.println("CONNECTED: " + session.getId());
synchronized(sessions){
sessions.add(session);
}
}
因此,带有 while 循环的线程应该打印出“没有可用的会话:[]”,直到调用 open(...) 方法。然而,只要 open 方法中的代码到达synchronized(sessions) {...},它就会说会话为空。考虑到在创建会话 ArrayList 的 init() 方法之前永远不会调用此方法,这没有任何意义。
所以,我之前所做的是添加以下代码:if(sessions == null) sessions = new ArrayList<Session>();,然后同步代码将运行。这将起作用,并且会话将被添加,但它不会出现在第二个线程中。第二个线程仍将循环并打印出没有可用的会话。我错过了什么?
堆栈跟踪:
2016-02-18T15:13:13.601-0500|严重:java.lang.NullPointerException 在 BotManager.open(BotManager.java:134) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 java.lang.reflect.Method.invoke(Method.java:606) 在 org.glassfish.tyrus.core.AnnotatedEndpoint.callMethod(AnnotatedEndpoint.java:431) 在 org.glassfish.tyrus.core.AnnotatedEndpoint.onOpen(AnnotatedEndpoint.java:468) 在 org.glassfish.tyrus.core.EndpointWrapper.onConnect(EndpointWrapper.java:446) 在 org.glassfish.tyrus.server.TyrusEndpoint.onConnect(TyrusEndpoint.java:146) 在 org.glassfish.tyrus.websockets.DefaultWebSocket.onConnect(DefaultWebSocket.java:122) 在 org.glassfish.tyrus.servlet.TyrusHttpUpgradeHandler.init(TyrusHttpUpgradeHandler.java:98) 在 org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:777) 在 org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673) 在 com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99) 在 org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174) 在 org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:357) 在 org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:260) 在 com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:188) 在 org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:191) 在 org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:168) 在 org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:189) 在 org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119) 在 org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:288) 在 org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:206) 在 org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:136) 在 org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:114) 在 org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77) 在 org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:838) 在 org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:113) 在 org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:115) 在 org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:55) 在 org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:135) 在 org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:564) 在 org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:544) 在 java.lang.Thread.run(Thread.java:745)
【问题讨论】:
-
sessions是如何定义的? -
全局变量 ArrayList
会话; -
能否请您发布您的
NullPointerException的堆栈跟踪? -
@ScottyPippen 你应该展示整个课程,包括会话成员的声明
-
您的同步存在死锁问题 - 您的可运行对象会锁定列表,直到其大小大于 0,并且您无法添加到列表中,直到它被解锁...
标签: java multithreading arraylist