我需要帮助设计基于多线程的应用程序,其中包括动态URL创建及其通过线程处理。
我在我的应用程序中使用spring scheduler,每30秒安排一次。从那个预定的方法我调用一些基于服务的apis,它在循环中,并且我需要每个API 1个线程池执行器,并且有1个线程处理。
由于此过程是从预定方法发生的,因此每次创建新线程池时,这都是问题所在。你可以在代码中看到。
我想要的是,如果对于任何API,如果线程池已经存在,那么该线程应该能够通过不创建新线程池并开始处理来自己识别。
如果需要更多信息,请告诉我。
欢迎并赞赏任何建议。谢谢
#API Properties
service.url=http://{0}.abc.net/xyz.php?
service.urls = abc1, abc2, abc3, abc4, abc5
@Service
public class APIServiceImpl implements APIService {
@Autowired
MsgService msgService;
private static final Logger LOGGER = Logger.getLogger(APIServiceImpl.class);
private static Properties fileProperties = PropertyUtility.getfileProperties();
@Scheduled(fixedDelayString = "30000")
public void getServiceMessage() throws ServiceException {
try {
long startTime = System.currentTimeMillis() / 1000L;
long endTime = startTime + 30;
String urlStr = fileProperties.getProperty("service.urls");
String[] urls = urlStr.split(",");
foreach(String url : urls){
serviceApi(url.trim(), startTime, endTime);
}
} catch (Exception e) {
throw new ServiceException(e);
}
}
private void serviceApi(String url, long startTime, long endTime) {
StringBuffer buffer = new StringBuffer();
buffer.append(java.text.MessageFormat.format(fileProperties.getProperty("service.url"), url));
buffer.append("starttime=" + startTime);
buffer.append("&endtime=" + endTime);
ExecutorService executor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<Runnable>(100), new ThreadPoolExecutor.CallerRunsPolicy());
executor.submit(new APIThreadHandler(buffer.toString(), messageService));
}
public class APIThreadHandler implements Runnable {
private static final Logger LOGGER = Logger.getLogger(APIThreadHandler.class);
private String url;
MsgService msgService;
public APIThreadHandler(String url, MsgService msgService) {
this.url = url;
this.msgService = msgService;
}
public void run() {
System.out.println("ThreadID: " + Thread.currentThread().getId());
try {
URL srcUrl = new URL(url);
List<Map<?, ?>> data = readObjectsFromCsv(srcUrl);
JSONArray jsonArray = new JSONArray(data);
for (int i = 0; i < jsonArray.length(); i++) {
msgService.sendMessage(jsonArray.getJSONObject(i));
}
} catch (Exception e) {
LOGGER.error("Exception occured - ", e);
}
}
private static List<Map<?, ?>> readObjectsFromCsv(URL url) {
List<Map<?, ?>> listMap = null;
try {
CsvSchema bootstrap = CsvSchema.emptySchema().withHeader();
CsvMapper csvMapper = new CsvMapper();
MappingIterator<Map<?, ?>> mappingIterator = csvMapper.readerFor(Map.class).with(bootstrap).readValues(url);
listMap = mappingIterator.readAll();
} catch (Exception e) {
LOGGER.error("Exception occured - ", e);
}
return listMap;
}
答案 0 :(得分:0)
您可以使用@ PostConstruct 初始化线程池一次,并且每次都重复使用它。只有在加载应用程序上下文时才会调用此项。
@PostConstruct
public void init() {
executor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<Runnable>(100), new ThreadPoolExecutor.CallerRunsPolicy());
}