Executor 服务不会处理 arraylist 中传递的所有数据

问题描述 投票:0回答:1

我正在尝试使用

ExecutorService
创建 3 个线程的线程池,但是每当我使用这些线程处理
ArrayList
时,只有列表的第二个第三个和最后一个元素被
run()
处理,然后进程卡在最后一个元素并不断处理它多次。这是我的代码:

public ResponseEntity<?> syncShopifyPriceRulesListToMongoV3(List<Long> ids) {
    logger.info("Start :: syncShopifyPriceRulesListToMongoV3 for ids size = "+ids.size());
    ExecutorService service = Executors.newFixedThreadPool(3);
    try {
        if (ids.size() > 0) {
            for (Long id : ids) {
                logger.info("id inside for"+id);
                ShopifyBulkSyncCoupons task = shopifyBulkSyncCoupons;
                task.setCouponId(id); // Set the 'id' value using the setter method
                service.execute(task);
            }
        }
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
    logger.info("End :: syncShopifyPriceRulesListToMongoV3");
    service.shutdown();
    return new ResponseEntity<>(HttpStatus.OK);
}

这是我的

ShopifyBulkSyncCoupons
课程:

@Component
public class ShopifyBulkSyncCoupons implements Runnable
{
    @Override
    public void run()
    {
        logger.info("Inside run for id "+CouponId);
        logger.info("ShopifyClientBean "+shopifyClient);

        PriceRuleService priceRuleService = new PriceRuleServiceImpl();

        ShopifyPriceRuleResponse priceRuleResponse = shopifyClient.getPriceRuleById(CouponId);
        if(null!=priceRuleResponse && null!=priceRuleResponse.getPriceRule()) {
            PriceRuleDetails priceRuleDetails = new PriceRuleDetails();
            List<Long> finalEntitledVariants = new ArrayList<>();
            priceRuleDetails = priceRuleService.mapShopifyPriceRuleToModel(priceRuleResponse.getPriceRule());
            if (!CollectionUtils.isEmpty(priceRuleDetails.getEntitledCollectionIds())) {
                List<Long> collectionIds = priceRuleDetails.getEntitledCollectionIds();
                List<ProductAttributes> prodAttr = productAttrRepository.findByCollectionsIn(collectionIds);
                for (ProductAttributes prod : prodAttr) {
                    finalEntitledVariants.add(prod.getVariantId());
                }
            }
            if (!CollectionUtils.isEmpty(priceRuleDetails.getEntitledProductIds())) {
                List<ProductAttributes> productAttributesList = productAttrRepository.findByProductIdIn(priceRuleDetails.getEntitledProductIds());
                for (ProductAttributes prod : productAttributesList) {
                    finalEntitledVariants.add(prod.getVariantId());
                }
            }
            if (!CollectionUtils.isEmpty(priceRuleDetails.getEntitledVariantIds())) {
                finalEntitledVariants.addAll(priceRuleDetails.getEntitledVariantIds());
            }
priceRuleDetails.setEntitledVariantIds(finalEntitledVariants);
            priceRuleDetailsRepo.save(priceRuleDetails);
        }
    }
}

我已经尝试了多种方法来解决这个问题。有人可以帮忙确定出了什么问题吗?

java executorservice
1个回答
0
投票

您没有提供足够的详细信息供我们调试,如评论中所述。

但是,我可以为您提供与您的代码并行的代码框架。

以下代码可以成功运行。我建议将你的实际工作一点一点添加到这个框架中,直到发现问题。

尝试资源

请注意,在现代 Java 中,

ExecutorService
AutoCloseable
。因此我们可以使用 try-with-resources 语法来正确关闭执行器服务。您的问题的代码在该区域中非常短 - 请参阅
ExecutorService
Javadoc 中提供给您的样板。添加到
close
ExecutorService
方法的默认实现本质上是该样板文件的副本。

避免
execute

请勿使用您的

Executor#execute
拨打
ExecutorService
。该方法被记录为“也许”在另一个线程上执行任务“或者”在同一线程上执行任务。为了确保后台线程的使用,请调用另一个方法,例如submit 骨架代码
定义任务类别:

package work.basil.example.coupon; import java.time.Duration; import java.time.Instant; import java.util.concurrent.ThreadLocalRandom; public class CouponProcessor implements Runnable { private final Long couponId; public CouponProcessor ( final Long couponId ) { this.couponId = couponId; } @Override public void run ( ) { System.out.println ( "Thread ID # " + Thread.currentThread ( ).threadId ( ) + " starting to process coupon ID # " + this.couponId + " at " + Instant.now ( ) ); try { Thread.sleep ( Duration.ofSeconds ( ThreadLocalRandom.current ( ).nextInt ( 1 , 7 ) ) ); } catch ( InterruptedException e ) { throw new RuntimeException ( e ); } System.out.println ( "Thread ID # " + Thread.currentThread ( ).threadId ( ) + " done process coupon ID # " + this.couponId + " at " + Instant.now ( ) ); } }

并编写一个

App
 类来处理一些优惠券 ID。

package work.basil.example.coupon; import java.time.Instant; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class App { public static void main ( String[] args ) { App app = new App ( ); app.demo ( ); } private void demo ( ) { System.out.println ( "INFO - Demo starting at " + Instant.now ( ) ); List < Long > couponIds = List.of ( 7L , 42L , 99L , 101L ); // Auto-boxing converts primitives to objects. try ( // Use try-with-resources syntax to automatically close the executor service when all submitted tasks have completed. ExecutorService executorService = Executors.newFixedThreadPool ( 3 ) ; ) { for ( Long couponId : couponIds ) { Runnable task = new CouponProcessor ( couponId ); executorService.submit ( task ); } } System.out.println ( "INFO - Executor service shutdown at " + Instant.now ( ) ); System.out.println ( "INFO - Demo done at " + Instant.now ( ) ); } }

运行时:

INFO - Demo starting at 2023-09-22T06:00:22.962114Z
Thread ID # 22 starting to process coupon ID # 42 at 2023-09-22T06:00:22.966858Z
Thread ID # 23 starting to process coupon ID # 99 at 2023-09-22T06:00:22.966860Z
Thread ID # 21 starting to process coupon ID # 7 at 2023-09-22T06:00:22.966859Z
Thread ID # 22 done process coupon ID # 42 at 2023-09-22T06:00:27.051596Z
Thread ID # 22 starting to process coupon ID # 101 at 2023-09-22T06:00:27.053034Z
Thread ID # 21 done process coupon ID # 7 at 2023-09-22T06:00:27.980626Z
Thread ID # 23 done process coupon ID # 99 at 2023-09-22T06:00:28.051538Z
Thread ID # 22 done process coupon ID # 101 at 2023-09-22T06:00:31.125844Z
INFO - Executor service shutdown at 2023-09-22T06:00:31.135371Z
INFO - Demo done at 2023-09-22T06:00:31.136004Z

注意:跨线程调用时,

System.out.println
 的输出不一定按时间顺序出现在控制台上。如果您关心顺序,请添加要研究的时间戳。


© www.soinside.com 2019 - 2024. All rights reserved.