简体   繁体   English

Spring Scheduler和线程池执行器

[英]Spring scheduler and Thread pool executor

I need help in designing multi thread based application which include dynamic url creation and its processing via thread. 我在设计基于多线程的应用程序时需要帮助,其中包括动态URL创建及其通过线程的处理。

I am using a spring scheduler in my application, which is scheduled every 30 seconds. 我在应用程序中使用spring调度程序,该调度程序每30秒调度一次。 And from that scheduled method I am invoking some service based apis which is in the loop and also in that I need 1 thread pool executor per API with 1 thread processing on it. 从该计划方法中,我正在调用一些基于服务的API,这些API处于循环中,并且每个API需要1个线程池执行程序以及1个线程处理能力。

As this process is happening from scheduled method, every time new thread pool created, which is the problem here. 由于此过程是通过计划的方法进行的,因此每次创建新的线程池时,这就是问题所在。 You can see in the code. 您可以在代码中看到。

What I want is, if for any of the API, if thread pool is already exists, then that thread should be able to recognize by its own by not creating the new thread pool and start processing. 我想要的是,如果对于任何一种API,如果线程池已经存在,则该线程应该能够通过不创建新的线程池并开始处理来自己识别。

Let me know, if more info needed. 让我知道,如果需要更多信息。

Any suggestions are welcome and appreciated. 任何建议都值得欢迎和赞赏。 Thanks 谢谢

#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;
}

You can use @ PostConstruct to initialize the Thread Pool once and reuse the same for each time. 您可以使用@ PostConstruct一次初始化线程池,然后每次重复使用该线程池。 This will be called only once when the app context gets loaded. 当应用程序上下文被加载时,将仅调用一次。

@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