專案裡多執行緒常用姿勢,很給力的使用方法

銘銘erom發表於2017-09-12

最近專案裡經常會有一部分大批量資料的校驗處理等對介面響應有要求的情景,這時候往往只能通過多執行緒的方式去處理請求,能達到快速響應

下面因為多執行緒用的比較多,所以需要複用程式碼,這裡我基於java8的函數語言程式設計抽出了共同方法,不侵佔業務實現,後面還有個多執行緒帶返回值的方式。大家可以參考參考思路。

public class TaskThreadPoolService {

private Logger logger = LoggerFactory.getLogger(TaskThreadPoolService.class);

/**
 * 預設執行緒大小
 */
private final static Integer DEFAULT_POOL_SIZE = 20;

/**
 * 預設最大活躍執行緒大小
 */
private final static Integer DEFAULT_MAX_ALIVE_POOL_SIZE = 50;

/**
 * 多執行緒執行無返回值方法
 * 執行緒池大小為20,最大活躍執行緒數50,存活時間為0的無邊界佇列執行緒池
 *
 * @param voidTaskMethodInteface
 * @param list
 * @param <T>
 */
public <T> void splitVoidTask(VoidTaskMethodInterface<T> voidTaskMethodInteface, List<T> list) throws Exception {
    splitVoidTask(voidTaskMethodInteface, list, DEFAULT_POOL_SIZE, DEFAULT_MAX_ALIVE_POOL_SIZE);
}

/**
 * 多執行緒執行無返回值方法(可指定部分執行緒池引數)
 *
 * @param voidTaskMethodInteface
 * @param list
 * @param <T>
 */
public <T> void splitVoidTask(VoidTaskMethodInterface<T> voidTaskMethodInteface, List<T> list, int poolSize, int maxSize) throws Exception {
    ThreadPoolExecutor executor = new ThreadPoolExecutor(poolSize, maxSize, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
    try {
        for (T t : list) {
            executor.submit(() -> {
                try {
                    voidTaskMethodInteface.exec(t);
                } catch (Throwable e) {
                    logger.error("splitVoidTask" + e.getMessage(), e);
                } finally {
                    logger.info("do what you want to do");
                }
            });
        }
    } catch (Exception e) {
        logger.error("多執行緒執行無返回值方法出現異常");
        throw new Exception("splitVoidTask error");
    } finally {
        executor.shutdown();
    }
}

/**
 * 帶返回值的多執行緒非同步等待所有結果返回的
 * 執行緒池大小為20,最大活躍執行緒數50,存活時間為0的無邊界佇列執行緒池
 * 單個返回的結果不能返回null,影響結果判定
 *
 * @param futureTaskMethodInteface
 * @param list
 * @param <T>
 * @param <F>
 * @return
 * @throws Exception
 */
public <T, F> Map<T, F> splitFutureTask(FutureTaskMethodInterface<T, F> futureTaskMethodInteface, List<T> list) throws Exception {
    return splitFutureTask(futureTaskMethodInteface, list, DEFAULT_POOL_SIZE, DEFAULT_MAX_ALIVE_POOL_SIZE);
}

/**
 * 帶返回值的多執行緒非同步等待所有結果返回的(可指定部分執行緒池引數)
 * 單個返回的結果不能返回null,影響結果判定
 *
 * @param futureTaskMethodInteface
 * @param list
 * @param <T>
 * @param <F>
 * @return
 * @throws Exception
 */
public <T, F> Map<T, F> splitFutureTask(FutureTaskMethodInterface<T, F> futureTaskMethodInteface, List<T> list, int poolSize, int maxSize) throws Exception {
    ThreadPoolExecutor executor = new ThreadPoolExecutor(poolSize, maxSize, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
    try {
        CountDownLatch countDownLatch = new CountDownLatch(list.size());
        Map<T, Future<F>> futureMap = new HashMap<>(list.size());
        for (T t : list) {
            Future<F> future = executor.submit(() -> {
                try {
                    F f = futureTaskMethodInteface.exec(t);
                    return f;
                } catch (Throwable e) {
                    logger.error("splitVoidTask" + e.getMessage(), e);
                    return null;
                } finally {
                    countDownLatch.countDown();
                }
            });
            futureMap.put(t, future);
        }
        Map<T, F> resultMap = new HashMap<>(futureMap.size());
        //檢測每個執行緒的執行結果,如果有future的返回結果為null,則認為執行失敗
        for (Map.Entry<T, Future<F>> entry : futureMap.entrySet()) {
            try {
                if (entry.getValue().get() == null) {
                    throw new Exception("splitFutureTask error");
                }
                resultMap.put(entry.getKey(), entry.getValue().get());
            } catch (Exception e) {
                logger.error("splitFutureTask error params:%s,error msg:%s", VJson.writeAsString(entry.getKey()), e.getMessage());
                throw new Exception("splitFutureTask error");
            }
        }
        return resultMap;
    } catch (Exception e) {
        logger.error("多執行緒執行無返回值方法出現異常");
        throw new Exception("splitFutureTask error");
    } finally {
        executor.shutdown();
    }
}
}


相關文章