为了账号安全,请及时绑定邮箱和手机立即绑定

创建新对象后控制方法调用的调用

创建新对象后控制方法调用的调用

LEATH 2021-12-01 19:54:39
我有一个预定的方法调用,它在预定的时间调用以下方法:private void doSomething(Map<String, String> someArguments) throws CustomException {  MyEnum runType = getRunType(someArguments);  switch (runType) {        case FRUIT:             new FruitClass().workNow();             break;        case VEGETABLE:             new VegetableClass().workNow();             break;        default:            // log that the type is not known       }   }的方法签名workNow是这样的:workNow() throws CustomExceptionworkNow方法运行几分钟并做一些工作。我的问题是,当一个workNowfor FRUIT(or VEGETABLE) 正在进行并且另一个调用发生在相同类型(FRUIT例如)时,它会创建一个新FruitClass实例并开始workNow并行执行它。我如何控制这种行为?我希望通过第二个对象的第二次调用等到第一个workNow到第一个对象未完成。澄清:并行调用FRUIT和VEGETABLE很好。我想控制相同类型的并行调用。两个以上FRUIT或两个以上VEGETABLE。我不能FruitClass和VegetableClass单身人士一样。我需要一些包装代码来new按照我想要的方式工作。
查看完整描述

3 回答

?
PIPIONE

TA贡献1829条经验 获得超9个赞

几个解决方案,我能想到:


解决方案1

static final String FRUIT = "FRUIT";

static final String VEGETABLE = "VEGETABLE";


private void doSomething(Map<String, String> someArguments) {

    MyEnum runType = getRunType(someArguments);

        switch (runType) {

            case FRUIT:

                synchronized (FRUIT){

                    new FruitClass().workNow();

                }

                break;


            case VEGETABLE:

                synchronized (VEGETABLE){

                    new VegetableClass().workNow();

                }

                break;


            default:

                // log that the type is not known 

        }

}

这可能比使用class对象更好,因为它们会更重并消耗内存。


解决方案2

这是对解决方案 1 的增强,以防有多个案例并且String不需要类级别。


private void doSomething(Map<String, String> someArguments) {

    MyEnum runType = getRunType(someArguments);

    synchronized(runType.toString().intern()) {//This prevents 2 FRUITs or 2 VEGETABLEs from entering

        switch (runType) {

            case FRUIT:

                    new FruitClass().workNow();

                break;


            case VEGETABLE:

                    new VegetableClass().workNow();

                break;


            default:

                // log that the type is not known 

        }

    }

}

两者都在一个略有不同的示例中进行了测试,但要说明这一点。


查看完整回答
反对 回复 2021-12-01
?
潇湘沐

TA贡献1816条经验 获得超6个赞

肯定有很多方法可以解决这个问题。我认为最简单的方法是为每种类型的任务使用单线程池:


//one pool per runType

private final ExecutorService fruitService = Executors.newSingleThreadExecutor();

private final ExecutorService vegService = Executors.newSingleThreadExecutor();

进而:


private void doSomething(Map<String, String> someArguments) {

    MyEnum runType = getRunType(someArguments);


    CompletableFuture<Void> result;


    switch (runType) {

    case FRUIT:

        result = CompletableFuture.runAsync(() -> 

                new FruitClass().workNow(), fruitService)

                .exceptionally((exception) -> {

                    if (exception instanceof CustomException) {

                        System.out.println("Failed with custom exception...");

                    }


                    return null; // returning Void

                });

        break;


    case VEGETABLE:

        result = CompletableFuture.runAsync(() -> 

                new VegetableClass().workNow(), vegService)

                .exceptionally((exception) -> {

                    if (exception instanceof CustomException) {

                        System.out.println("Failed with custom exception...");

                    }


                    return null; // returning Void

                });


        break;


    default:

        throw new RuntimeException();

    }


    result.join();

}

这只是强制并发调用等待资源,并且不会同时运行 2 个相同类型的任务。


它提供了异步执行的额外好处,尽管您可以在需要时显式阻塞以等待结果。


查看完整回答
反对 回复 2021-12-01
?
慕标5832272

TA贡献1966条经验 获得超4个赞

在类对象上进行同步,这足以避免在完成之前创建另一个类:


private void doSomething(Map<String, String> someArguments) {

    MyEnum runType = getRunType(someArguments);

    switch (runType) {

        case FRUIT:

            synchronized (FruitClass.class){

                new FruitClass().workNow();

            }

            break;


        case VEGETABLE:

            synchronized (VegetableClass.class){

                new VegetableClass().workNow();

            }

            break;


        default:

            // log that the type is not known 

    }

}

synchronized在类对象上使用类实例作为监视器。类对象实际上是一个单例(在运行时代表类元数据的对象),并且这个块中只能有一个线程。


查看完整回答
反对 回复 2021-12-01
  • 3 回答
  • 0 关注
  • 179 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信