怎么写一个高效稳定的缓存队列?

miracleliu 2014-02-07 06:05:31
我写了一个,大家给点意见

队列和executor
public class SyncQueue {

public static final ExecutorService executorService = Executors.newFixedThreadPool(10);

public static final BlockingQueue<String> queue = new ArrayBlockingQueue<String>(200);

public static final Deque<String> dq = new LinkedBlockingDeque<String>(10);
// public static boolean addjob(String jsonData) {
// return queue.offer(jsonData);
// }
}


servlet,接受请求

public class Clean extends HttpServlet {
private static final long serialVersionUID = 1L;

private static Logger log = Logger.getLogger(Clean.class);

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

String jsonData = request.getParameter("json");

if (jsonData != null && !jsonData.equals("")) {

if (SyncQueue.queue.offer(jsonData)) {//添加到缓存队列
SyncQueue.executorService.execute(new DealThread());//调用线程执行
log.info("ok," + jsonData);
response.sendError(HttpServletResponse.SC_OK);
} else {
log.info("full !!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + jsonData);
response.sendError(HttpServletResponse.SC_TEMPORARY_REDIRECT);
}
} else {
log.info("wrong param" + jsonData);
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
}

}

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

this.doGet(request, response);
}

}


处理线程
public class DealThread implements Runnable {

private static Logger log = Logger.getLogger(DealThread.class);

private String name = "";

public DealThread() {
}

public DealThread(String name) {
this.name = name;
}

@Override
public void run() {

String json = SyncQueue.queue.poll();
if (json != null) {
log.info("josn:" + json);
long start = System.currentTimeMillis();
Connection conn = DBPool.getInstance().getConnection("live");
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
pstmt = conn.prepareStatement("select * from channel where id=?");
pstmt.setInt(1, Integer.parseInt(json));
rs = pstmt.executeQuery();
while (rs.next()) {
log.info("thread," + Thread.currentThread().getName() + ":" + rs.getString("channelName"));
}
Thread.sleep(new Random().nextInt(4000));//for test模拟大任务
} catch (SQLException e) {
retry(json);
log.error(" sql exception ;", e);
} catch (InterruptedException e) {
retry(json);
log.error(" interrupted; ", e);
} finally {
DBPool.close(pstmt, rs, conn);
}
long exeTime = System.currentTimeMillis() - start;
log.info("thread," + Thread.currentThread().getName() + ":" + exeTime + "ms");
}
}

private void retry(String json) {
Connection conn = DBPool.getInstance().getConnection("live");
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
pstmt = conn.prepareStatement("select * from channel where id=?");
pstmt.setInt(1, Integer.parseInt(json));
rs = pstmt.executeQuery();
while (rs.next()) {
log.info("thread," + Thread.currentThread().getName() + ":" + rs.getString("channelName"));
}
Thread.sleep(new Random().nextInt(4000));//for test模拟大任务
} catch (SQLException e) {
log.error(" sql exception ;", e);
} catch (InterruptedException e) {
log.error(" interrupted; ", e);
} finally {
DBPool.close(pstmt, rs, conn);
}
}

}
...全文
373 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
致知Fighting 2014-02-08
  • 打赏
  • 举报
回复
线程池同样也支持把超出的任务放进队列的操作,为什么lz要自己写一个队列先入列再起线程,感觉和直接用线程池没有区别,反而复杂了
  • 打赏
  • 举报
回复
队列JAVA里不是先现成的嘛?为什么要自己写?
  • 打赏
  • 举报
回复
感觉直接使用线程池就好了,没看出来这里使用队列的意义在哪?
miracleliu 2014-02-08
  • 打赏
  • 举报
回复
又没人理了。。我顶
miracleliu 2014-02-08
  • 打赏
  • 举报
回复
引用 7 楼 bao110908 的回复:
[quote=引用 5 楼 miraclestar 的回复:] [quote=引用 2 楼 bao110908 的回复:] 感觉直接使用线程池就好了,没看出来这里使用队列的意义在哪?
直接用线程池的话, 如果线程池处理不过来,怎么通知客户端,说已经满了处理不过来了?[/quote] ThreadPoolExecutor 类不是可以使用相关的 RejectedExecutionHandler 接口么?默认的是 AbortPolicy 实现,即抛出异常。[/quote] 哦,thank you,这样改了
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

		String jsonData = request.getParameter("json");
		PrintWriter out = response.getWriter();

		if (jsonData != null && !jsonData.equals("")) {
			try{
				SyncQueue.exe.execute(new DealThread2(jsonData));
				out.print("ok");
			} catch (RejectedExecutionException e) {
				out.print("full");
			}

		} else {
			log.info("wrong param" + jsonData);
			out.print("wrong param");
			response.sendError(HttpServletResponse.SC_BAD_REQUEST);
		}
	}
  • 打赏
  • 举报
回复
引用 5 楼 miraclestar 的回复:
[quote=引用 2 楼 bao110908 的回复:] 感觉直接使用线程池就好了,没看出来这里使用队列的意义在哪?
直接用线程池的话, 如果线程池处理不过来,怎么通知客户端,说已经满了处理不过来了?[/quote] ThreadPoolExecutor 类不是可以使用相关的 RejectedExecutionHandler 接口么?默认的是 AbortPolicy 实现,即抛出异常。
赵增光 2014-02-08
  • 打赏
  • 举报
回复
不管是否能用的上,想说分享就是一种美德。
miracleliu 2014-02-08
  • 打赏
  • 举报
回复
引用 2 楼 bao110908 的回复:
感觉直接使用线程池就好了,没看出来这里使用队列的意义在哪?
直接用线程池的话, 如果线程池处理不过来,怎么通知客户端,说已经满了处理不过来了?

67,515

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧