当前位置: 首页 > 知识库问答 >
问题:

Spring调度器和线程池执行器

宋志学
2023-03-14

我需要帮助设计基于多线程的应用程序,包括动态url创建和线程处理。

我在我的应用程序中使用了一个Spring调度器,它每30秒调度一次。从这个调度方法中,我调用了一些基于服务的api,它在循环中,而且我需要每个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;
}

共有1个答案

戚建白
2023-03-14

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

@PostConstruct
public void init() {
 executor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS,
    new ArrayBlockingQueue<Runnable>(100), new ThreadPoolExecutor.CallerRunsPolicy());
}
 类似资料:
  • 我们正在对使用SpringBoot 2.2.2和Spring执行器的应用程序进行性能测试。 我们希望监控: 正在使用多少tomcat线程 有多少tomcat请求正在排队 正在使用多少个ThreadPoolTaskExector线程(我们将@Async与线程池一起用于某些任务) 执行器中是否提供此信息?我看不到需要使用哪些指标。

  • 我正在使用线程池执行器更改遗留设计。详情如下:- 遗留:-对于遗留设计,在应用程序启动时创建600个线程。和放置在各种池中,然后在需要时提取这些池,并将任务分配给相应的线程。 新:-在新设计中,我将线程池替换为执行器服务 我观察到的是,对于Executor,在启动时不会创建线程。它们是在从客户端激发请求时创建的。因此,与前一个线程相比,在内存中创建的线程要少得多。 但我的问题是,这样做是否正确,因

  • 我对为什么以下演员不起作用感到非常困惑: schduledThreadPoolExector实现了schduledExecutorService。如果我不能将它与实际的类一起使用,这个执行器调用的意义是什么? 我用错了吗(可能),有人能提供一些指导吗?

  • 我无法找到必要的信息,无论是在文档中还是在这里已经存在的问题中,这就是为什么我自己创建了一个(我还不能在类似的帖子下提问)。 我需要知道的是Spring任务执行器和调度器之间的关系。我当前的配置如下所示: 我不确定的是它是如何工作的。“谁”运行我的任务?是调度器,因为任务是和他一起安排的吗?或者调度器只是创建它们,放在队列中,由执行者运行它们? 如果没有,运行的是scheduler,我必须在特定类

  • 我正在编写一个定制的ThreadPoolExecutor,具有以下额外功能:- > 如果有理想的线程,并且随着任务的到来,将该任务分配到队列中,而不是将其添加到队列中。 如果所有线程(最大池大小)都忙,则在新任务到来时,使用RejectionHandler的reject方法将它们添加到队列中 我已经重写了线程池执行程序的java 1.5版本的执行方法。 新守则如下:- 遗留代码如下所示:- 现在正

  • Java SE6文档中的ThreadPoolExecutor类具有以下方法: 返回正在积极执行任务的线程的大致数目。 这里近似和积极执行是什么意思? 在调用之前、期间和之后,是否保证 null 我已经研究了线程池执行器监视需求,以及如何在java中判断线程池中是否有可用的线程,但它们没有回答我的查询。