多线程遇到的坑
项目中,遇到了一个需要同时处理一组业务的需求,之前是采用单线程处理,响应时间达到了20多秒,回家了电脑配置也低,于是部署到了服务器测试了下,妈呀,快了很多,差不多9秒。但是还是不行啊,我这个是个推送的监控画面(websocket),理想下2-3秒最合适。没办法,只能改代码,加了各种缓冲技术,又测试了一下,又快了一半的时间,5秒左右,但是还是不能满足啊。
没有办法了,看了下服务器配置,2核!!!只能用多线程干一下了,于是写下了如下代码:
@Scheduled(cron = "00/1 * * * * ?")
public void getAllMessageYssj() {
log.info("连接websocket人数"+WebSocketJzssdata.getOnlineCount()+"");
String times = null;
Date time = new Date();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
times=df.format(time);
log.info(">>>>>>>>>>"+times+"执行定时任务开始<<<<<<<<<<<<<<<<");
List<String> list = Arrays.asList(new String[16]);
ExecutorService exector = Executors.newFixedThreadPool(16);
int threadNumber = 16;
final CountDownLatch countDownLatch = new CountDownLatch(threadNumber);
for (int i = 0; i < threadNumber; i++) {
final int threadID = i;
exector.execute(
() -> {
try {
log.info(String.format("异步执行threadID:[%s] 开始!!", threadID));
String message1 = “调取service方法,业务处理”;
list.set(threadID,message1);//把所有的返回结果放到集合中
log.info(String.format("异步执行threadID:[%s] finished!!", threadID));
} catch (Exception e) {
e.printStackTrace();
} finally {
countDownLatch.countDown(); //
}
}
);
}
try {
countDownLatch.await();
JSONObject returnValue = new JSONObject(new LinkedHashMap());
returnValue.put("xxx",list);
try {
//log.info(">>>>>>>>>>websocket任务开始<<<<<<<<<<<<<<<<");
WebSocketJzssdata.sendInfo(returnValue.toString());
//log.info(">>>>>>>>>>websocket任务end<<<<<<<<<<<<<<<<");
log.info(">>>>>>>>>>"+times+"执行定时任务结束<<<<<<<<<<<<<<<<");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
看日志:
1.9秒搞定,最算大功告成。
第二天悲剧发生了,页面打不开,服务器奔溃了。赶快查看服务器看日志,悲剧再次发生,用我自己的账号登录服务器,登录不上去(自己内心在怀疑阿里服务器又挂了)????换了一个root账号登录,进去了,赶快看日志吧。ava.lang.RuntimeException:java.lang.OutOfMemoryError:unabletocreatenewnativethread!!!线程满了????纳尼,不是阿里的问题,是自己代码问题。
看了下java的线程,一直增加。。。。恍然大悟,没关闭线程。
exector.shutdown();!!!搞定了。坑了自己了。
写多线程一定要注意!!!!尤其是定时任务中,频率特别高,一会就没了。