簡體   English   中英

在Java中同時運行兩個任務

[英]Running two tasks at the same time in Java

我想同時執行這兩段代碼。 這是我到目前為止的代碼:

@Path("/cases")
public class CaseResource {

    @GET
    @Path("/getCaseNumber")
    @Produces(MediaType.TEXT_PLAIN)
    public String getNextCaseNumber(
            @ApiParam(value = "tenant id", required = true)
            @HeaderParam("tenant_id") String tenantId) throws Exception {

        //Piece #1
        String caseNum1 = new CaseHelper(new ConfigurationService(),new CaseService()).getNextCaseNumberFromDatabase(tenantId);
        Case tempCase = new Case();
        tempCase.setCaseStatusCode(new CodeService().getCodeForKeyGroup("ACTIVE","CASE_STATUS"));
        caseService.saveCase(tempCase, tenantId);

        //Piece #2 
        String caseNum2= new CaseHelper(new ConfigurationService(),new CaseService()).getNextCaseNumberFromDatabase(tenantId);




        String caseNumbers = "{case1: " + caseNum1 + ", case2:" + caseNum2 + "}";
        return caseNumbers;
    }
}

一切都在這里工作,但我想同時做以下任務:

Task1:輸出caseNum1,將新案例保存到數據庫

Task2:輸出caseNum2

這是我試圖做的事情:

@Path("/cases")
public class CaseResource {
    String  caseNum1;
    String caseNum2;


    @GET
    @Path("/getCaseNumber")
    @Produces(MediaType.TEXT_PLAIN)
    public String getNextCaseNumber(
            @ApiParam(value = "tenant id", required = true)
            @HeaderParam("tenant_id") final String tenantId) throws Exception {

        new Thread(new Runnable() {
            public void run() {
                caseNum1= new CaseHelper(new ConfigurationService(),new CaseService()).getNextCaseNumberFromDatabase(tenantId);
                Case tempCase = new Case();
                tempCase.setCaseStatusCode(new CodeService().getCodeForKeyGroup("ACTIVE","CASE_STATUS"));
                caseService.saveCase(tempCase, tenantId);
            }
        }).start();

        new Thread(new Runnable() {
            public void run() {
                caseNum2 = new CaseHelper(new ConfigurationService(),new CaseService()).getNextCaseNumberFromDatabase(tenantId);

            }
        }).start();

        String caseNumbers = "{case1: " + caseNum1 + ", case2:" + caseNum2  + "}" ;

        return caseNumbers;
    }
}

但是caseNum1和caseNum2返回null。 知道為什么嗎? 可能沒有正確調用run()。 雖然,我甚至不確定我是否正在做這個線程。 有任何想法嗎?

嘗試這個:

    ...

    CountDownLatch latch = new CountDownLatch(2);


    new Thread(new Runnable() {
        public void run() {
            caseNum1= new CaseHelper(new ConfigurationService(),new CaseService()).getNextCaseNumberFromDatabase(tenantId);
            Case tempCase = new Case();
            tempCase.setCaseStatusCode(new CodeService().getCodeForKeyGroup("ACTIVE","CASE_STATUS"));
            caseService.saveCase(tempCase, tenantId);
            latch.countDown();
        }
    }).start();

    new Thread(new Runnable() {
        public void run() {
            caseNum2 = new CaseHelper(new ConfigurationService(),new CaseService()).getNextCaseNumberFromDatabase(tenantId);
            latch.countDown();

        }
    }).start();

    latch.await();

    ...

您必須等待線程終止,否則代碼將在線程填充值之前運行。 運行新線程時,計算繼續,並且執行順序未知。 所以你的主線程可能會在t1t2實際計算出值之前t1返回。

 Thread t1 = new Thread(new Runnable() {
       public void run() {
                caseNum1= new CaseHelper(new ConfigurationService(),new CaseService()).getNextCaseNumberFromDatabase(tenantId);
                Case tempCase = new Case();
                tempCase.setCaseStatusCode(new CodeService().getCodeForKeyGroup("ACTIVE","CASE_STATUS"));
                caseService.saveCase(tempCase, tenantId);
            }
        });

 t1.start();

 Thread t2 = new Thread(new Runnable() {
        public void run() {
            caseNum2 = new CaseHelper(new ConfigurationService(),new CaseService()).getNextCaseNumberFromDatabase(tenantId);

        }
    });
t2.start();

t1.join();
t2.join();

String caseNumbers = "{case1: " + caseNum1 + ", case2:" + caseNum2  + "}" ;

我可以看到幾個問題:

  1. 您的代碼不是線程安全的。 無法保證您創建的任何一個線程的寫入都將在父線程中看到。 您需要同步您正在執行的操作或使字段不穩定
  2. 在線程上調用start()后繼續執行。 線程並行執行。 因此,代碼中的子線程中的寫入與父線程中的讀取之間存在競爭條件。 您需要在父線程和子線程之間進行協調,例如通過調用它們上的join()。

您應該查看servlet 3.0異步操作。 在這種情況下,您可以保留響應,直到完成異步操作。

從春季開始查看此博客: https//spring.io/blog/2012/05/07/spring-mvc-3-2-preview-introducing-servlet-3-async-support

我認為好方法是使用Feature 在下面的示例中,您在並行線程中運行兩個任務, 您仍然可以使用異常 ,就像在單線程示例中一樣。

public String getNextCaseNumber(String tenantId) throws Exception {
    ExecutorService executor = Executors.newFixedThreadPool(2);
    Future<String> caseNum1 = executor.submit(() -> {
        String caseNum = new CaseHelper(new ConfigurationService(), new CaseService()).getNextCaseNumberFromDatabase(tenantId);
        Case tempCase = new Case();
        tempCase.setCaseStatusCode(new CodeService().getCodeForKeyGroup("ACTIVE", "CASE_STATUS"));
        caseService.saveCase(tempCase, tenantId);
        return caseNum;
    });
    Future<String> caseNum2 = executor.submit(() -> new CaseHelper(new ConfigurationService(), new CaseService()).getNextCaseNumberFromDatabase(tenantId));

    return String.format("{case1: %s, case2: %s}", caseNum1.get(), caseNum2.get());
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM