亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Java:如果另一個線程已經在其中,則新線程將跳過同步方法

Java:如果另一個線程已經在其中,則新線程將跳過同步方法

哈士奇WWW 2023-02-23 10:52:09
要求我需要能夠通過 POST 調用觸發(長時間運行的)作業并立即返回。一次只有一個線程可以運行作業。這項工作是一項昂貴的工作,如果一項工作已經在進行中,我希望這項工作的所有未來觸發器都不做任何事情。代碼@RestControllerpublic class SomeTask {    private SomeService someService;    @Autowired     public SomeTask(SomeService someService) {        this.someService = someService;     }    @Async // requirement 1     @RequestMapping(method = RequestMethod.POST, path = "/triggerJob")     public void triggerJob() {         expensiveLongRunningJob();     }    /**      * Synchronized in order to restrict multiple invocations. // requirement 2      *      */     private synchronized void expensiveLongRunningJob() {          someService.executedJob();     } }問題上面的代碼要求 1 和 2 得到滿足。滿足要求 3 的最佳方法是什么(作為 POST 調用的結果創建的新線程跳過同步方法并在獲取鎖失敗時立即返回)?
查看完整描述

2 回答

?
嚕嚕噠

TA貢獻1784條經驗 獲得超7個贊

同步不是完成這項工作的正確工具。你可以這樣做:


@RestController

public class SomeTask {


    private SomeService someService;

    private final AtomicBoolean isTriggered = new AtomicBoolean();


    @Autowired

    public SomeTask(SomeService someService) {

        this.someService = someService;

    }


    @Async // requirement 1

    @RequestMapping(method = RequestMethod.POST, path = "/triggerJob")

    public void triggerJob() {

        if (!isTriggered.getAndSet(true)) {

            try {

                expensiveLongRunningJob();

            } finally {

                isTriggered.set(false);

            }

        }

    }


    /**

     * only runs once at a time, in the thread that sets isTriggered to true

     */

    private void expensiveLongRunningJob() { 

        someService.executedJob();

    }

}


查看完整回答
反對 回復 2023-02-23
?
ITMISS

TA貢獻1871條經驗 獲得超8個贊

對于要求 1,如果你只想使用@Async,你應該在服務方法而不是控制器方法上使用它。但請注意,通過使其異步,您將失去對作業的控制,并且無法進行故障處理,除非您通過實現接口來實現@Async和Future處理故障AsyncUncaughtExceptionHandler。


對于要求 3,您可以在服務中有一個 volatile 布爾字段,它在開始作業流程之前設置,并在作業流程完成后取消設置。在您的控制器方法中,您可以檢查服務的易失性布爾字段以確定作業是否正在執行,如果作業正在進行則返回適當的消息。另外,確保在處理AsyncUncaughtExceptionHandler接口實現失敗時取消設置布爾字段。


服務:


@Service

public class SomeService {


    public volatile boolean isJobInProgress = false;


    @Async

    public Future<String> executeJob() {

        isJobInProgress = true;

        //Job processing logic

        isJobInProgress = false;

    }

}

控制器:


@RestController

public class SomeTask {


    @Autowired

    private SomeService someService;


    @RequestMapping(method = RequestMethod.POST, path = "/triggerJob")

    public void triggerJob() {

        if (!someService.isJobInProgress){

            someService.executeJob(); //can have this in a sync block to be on the safer side. 

        } else {

            return;

        }

    }


}

AsyncUncaughtExceptionHandler 的實現:


public class CustomAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {


    @Autowired

    private SomeService someService;


    @Override

    public void handleUncaughtException(

            Throwable throwable, Method method, Object... obj) {


        //Handle failure

        if (someService.isJobInProgress){

            someService.isJobInProgress = false;

        }

    }

}

@異步配置:


@Configuration

@EnableAsync

public class SpringAsyncConfig implements AsyncConfigurer {


    @Override

    public Executor getAsyncExecutor() {

        return new ThreadPoolTaskExecutor();

    }


    @Override

    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {

        return new CustomAsyncExceptionHandler();

    }


}


查看完整回答
反對 回復 2023-02-23
  • 2 回答
  • 0 關注
  • 136 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號