2016-01-20 41 views
3

我想同時執行這兩段代碼。下面的代碼我到目前爲止:在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; 
    } 
} 

一切都在這裏工作,但我想在同一時間做了以下工作:

任務1:輸出caseNum1,新的情況下保存到數據庫

任務2:輸出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()沒有正確調用。雖然,我甚至不確定我是否正在執行此線程權限。有任何想法嗎?

+0

對於以** **確切的時間看相同於[此](http://stackoverflow.com/questions/3376586/how-to-start-two-threads-at-exactly-啓動線程同一時間) – Dan

+0

它看起來好像你要運行這個作爲一個Web服務。你可能想重新考慮使用實例變量,因爲你可能有多個併發請求 – user1675642

回答

2

試試這個:

... 

    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(); 

    ... 
+0

該代碼仍然不是線程安全的,因爲變量不是volatile/synchronized,所以這不能保證能正常工作 – user1675642

+0

不正確 - CountDownLatch提供必要的保證,請參閱https://docs.oracle.com/javase/8 /docs/api/java/util/concurrent/CountDownLatch.html –

+0

你說得對。明確地值得一提的是。 – user1675642

0

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

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 + "}" ; 
+0

當我嘗試Thread t1 = new Thread(new Runnable()時,它說它需要java.lang.Thread並且它找到了一個void。 – Jay266

+0

對不起,我沒有注意到最後的start()。首先創建線程對象然後運行它們。 –

0

一對夫婦的,我可以看到的問題:

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

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

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()); 
}