我正在尝试使用
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
是 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
的输出不一定按时间顺序出现在控制台上。如果您关心顺序,请添加要研究的时间戳。