Java tutorial
/* * Copyright Beijing 58 Information Technology Co.,Ltd. * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.bj58.spat.gaea.server.util.async; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; import org.apache.commons.logging.Log; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeoutException; import org.apache.commons.logging.LogFactory; import com.bj58.spat.gaea.server.util.jsr166.LinkedTransferQueue; import com.bj58.spat.gaea.server.util.jsr166.TransferQueue; class AsyncWorker extends Thread { private static final Log logger = LogFactory.getLog(AsyncWorker.class); /** * */ private final TransferQueue<AsyncTask> taskQueue; /** * */ private final Executor executor; /** * ?? */ private boolean isStop = false; private boolean timeoutEffect = false; AsyncWorker(Executor executor, boolean timeoutEffect) { this.taskQueue = new LinkedTransferQueue<AsyncTask>(); this.executor = executor; this.timeoutEffect = timeoutEffect; } @Override public void run() { if (this.timeoutEffect) { while (!isStop) { execTimeoutTask(); } } else { while (!isStop) { execNoTimeLimitTask(); } } } /** * * @param task */ void addTask(AsyncTask task) { this.taskQueue.offer(task); } /** * ?(stop is final) */ void end() { this.isStop = true; logger.info("-------------------async workder is stop-------------------"); } private void execNoTimeLimitTask() { AsyncTask task = null; try { task = taskQueue.take(); if (task != null) { if ((System.currentTimeMillis() - task.getAddTime()) > task.getQtimeout()) { task.getHandler().exceptionCaught(new TimeoutException("async task timeout!")); return; } else { Object obj = task.getHandler().run(); task.getHandler().messageReceived(obj); } } else { logger.error("execNoTimeLimitTask take task is null"); } } catch (InterruptedException ie) { } catch (Throwable ex) { if (task != null) { task.getHandler().exceptionCaught(ex); } } } private void execTimeoutTask() { try { final AsyncTask task = taskQueue.take(); if (task != null) { if ((System.currentTimeMillis() - task.getAddTime()) > task.getQtimeout()) { task.getHandler().exceptionCaught(new TimeoutException("async task timeout!")); return; } else { final CountDownLatch cdl = new CountDownLatch(1); executor.execute(new Runnable() { @Override public void run() { try { Object obj = task.getHandler().run(); task.getHandler().messageReceived(obj); } catch (Throwable ex) { task.getHandler().exceptionCaught(ex); } finally { cdl.countDown(); } } }); cdl.await(getTimeout(task.getTimeout(), taskQueue.size()), TimeUnit.MILLISECONDS); if (cdl.getCount() > 0) { task.getHandler().exceptionCaught(new TimeoutException("async task timeout!")); } } } else { logger.error("execTimeoutTask take task is null"); } } catch (InterruptedException ie) { logger.error(""); } catch (Throwable e) { logger.error("get task from poll error", e); } } /** * (??) * @param timeout * @param queueLen * @return */ private int getTimeout(int timeout, int queueLen) { if (queueLen <= 0 || timeout < 5) { return timeout; } float rad = (float) ((float) timeout - (float) timeout * 0.006 * queueLen); int result = (int) rad < 5 ? 5 : (int) rad; if (queueLen > 100) { logger.warn( "async task,queueLen:" + queueLen + ",fact timeout:" + result + ",original timeout:" + timeout); } return result; } }