繁体   English   中英

Spring Scheduler和线程池执行器

[英]Spring scheduler and Thread pool executor

我在设计基于多线程的应用程序时需要帮助,其中包括动态URL创建及其通过线程的处理。

我在应用程序中使用spring调度程序,该调度程序每30秒调度一次。 从该计划方法中,我正在调用一些基于服务的API,这些API处于循环中,并且每个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;
}

您可以使用@ PostConstruct一次初始化线程池,然后每次重复使用该线程池。 当应用程序上下文被加载时,将仅调用一次。

@PostConstruct
public void init() {
 executor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS,
    new ArrayBlockingQueue<Runnable>(100), new ThreadPoolExecutor.CallerRunsPolicy());
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM