001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.eclipse.aether.util.concurrency; 020 021import java.util.concurrent.Executor; 022import java.util.concurrent.ExecutorService; 023import java.util.concurrent.LinkedBlockingQueue; 024import java.util.concurrent.ThreadPoolExecutor; 025import java.util.concurrent.TimeUnit; 026 027import org.eclipse.aether.RepositorySystemSession; 028import org.eclipse.aether.util.ConfigUtils; 029 030/** 031 * Utilities for executors and sizing them. 032 * 033 * @since 1.9.5 034 */ 035public final class ExecutorUtils { 036 /** 037 * Shared instance of "direct executor". 038 */ 039 public static final Executor DIRECT_EXECUTOR = Runnable::run; 040 041 /** 042 * Creates new thread pool {@link ExecutorService}. The {@code poolSize} parameter but be greater than 1. 043 */ 044 public static ExecutorService threadPool(int poolSize, String namePrefix) { 045 if (poolSize < 2) { 046 throw new IllegalArgumentException("Invalid poolSize: " + poolSize + ". Must be greater than 1."); 047 } 048 return new ThreadPoolExecutor( 049 poolSize, 050 poolSize, 051 3L, 052 TimeUnit.SECONDS, 053 new LinkedBlockingQueue<>(), 054 new WorkerThreadFactory(namePrefix)); 055 } 056 057 /** 058 * Returns {@link #DIRECT_EXECUTOR} or result of {@link #threadPool(int, String)} depending on value of 059 * {@code size} parameter. 060 */ 061 public static Executor executor(int size, String namePrefix) { 062 if (size <= 1) { 063 return DIRECT_EXECUTOR; 064 } else { 065 return threadPool(size, namePrefix); 066 } 067 } 068 069 /** 070 * To be used with result of {@link #executor(int, String)} method, shuts down instance if it is 071 * {@link ExecutorService}. 072 */ 073 public static void shutdown(Executor executor) { 074 if (executor instanceof ExecutorService) { 075 ((ExecutorService) executor).shutdown(); 076 } 077 } 078 079 /** 080 * Retrieves and validates requested thread count based on session and specified keys, or if none provided, the 081 * provided default value. This method validates result on top of what {@link ConfigUtils} does. 082 * 083 * @throws IllegalArgumentException if default value is less than 1. 084 * @see ConfigUtils#getInteger(RepositorySystemSession, int, String...) 085 */ 086 public static int threadCount(RepositorySystemSession session, int defaultValue, String... keys) { 087 if (defaultValue < 1) { 088 throw new IllegalArgumentException("Invalid defaultValue: " + defaultValue + ". Must be greater than 0."); 089 } 090 int threadCount = ConfigUtils.getInteger(session, defaultValue, keys); 091 if (threadCount < 1) { 092 throw new IllegalArgumentException("Invalid value: " + threadCount + ". Must be greater than 0."); 093 } 094 return threadCount; 095 } 096}