在Java中同时运行两个任务

时间:2016-01-20 17:08:56

标签: java multithreading hibernate

我想同时执行这两段代码。这是我到目前为止的代码:

@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()。虽然,我甚至不确定我是否正在做这个线程。有什么想法吗?

5 个答案:

答案 0 :(得分: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();

    ...

答案 1 :(得分: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  + "}" ;

答案 2 :(得分:0)

我可以看到几个问题:

  1. 您的代码不是线程安全的。我们无法保证您创建的任何一个线程的写入都将在父线程中看到。您需要同步您正在进行的操作或使字段变为volatile
  2. 在线程上调用start()后继续执行。线程并行执行。因此,代码中的子线程中的写入与父线程中的读取之间存在竞争条件。您需要在父线程和子线程之间进行协调,例如通过调用它们上的join()。

答案 3 :(得分:0)

您应该查看servlet 3.0异步操作。 在这种情况下,您可以保留响应,直到您完成异步操作。

从春天看这个博客: https://spring.io/blog/2012/05/07/spring-mvc-3-2-preview-introducing-servlet-3-async-support

答案 4 :(得分: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());
}