Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在同一对象上使用Fork和Join_Java_Multithreading_Spring Boot - Fatal编程技术网

Java 在同一对象上使用Fork和Join

Java 在同一对象上使用Fork和Join,java,multithreading,spring-boot,Java,Multithreading,Spring Boot,我正在做一个spring boot项目。我有一个场景,需要进行服务调用,从DB获取数据并更新响应对象。 我希望在两个不同的线程中执行这些操作,以获得更好的性能 我尝试使用以下代码 Thread t1 = new Thread(new Runnable(){ public void run(){ try { //make service call and update response object. } catch

我正在做一个spring boot项目。我有一个场景,需要进行服务调用,从DB获取数据并更新响应对象。 我希望在两个不同的线程中执行这些操作,以获得更好的性能

我尝试使用以下代码

Thread t1 = new Thread(new Runnable(){

    public void run(){
        try {
            //make service call and update response object.
        }
        catch(Exception e){

        }
    }
    });

    t1.start();
    //fetch data from DB and update the response object.

    t1.join();
但是,当我尝试点击请求并让它在不放置任何断点的情况下完成(基本上按照我想要的顺序执行)时,这是行不通的

是否有更好的替代方案来实现这一点

我可以用叉子在这里连接吗? 如果是,我如何使用它

请注意,来自服务调用的数据和来自DB的数据并不相互依赖

进一步挖掘后,我在oracle文档中找到了以下信息

首先,fork/join任务应该在内存中作为“纯”任务运行 没有I/O操作发挥作用的算法。也, 应尽量避免任务之间通过共享状态进行通信 尽可能多,因为这意味着锁定可能必须 表演。理想情况下,任务只在一个任务分叉另一个任务时进行通信 或者当一个任务加入另一个任务时


首先,你用你通过的文件的第一个例子说:

以这种方式直接操作线程对于简单的示例来说很好, 但通过并发编程,这样的代码可以很快变得 容易出错,尤其是当多个线程需要协作以 执行更大的任务。在这种情况下,需要修改它们的控制流 协调

因此,在同一份文件中,建议使用执行者:

执行器,它是对普通旧线程的增强,因为 它们是从线程池管理中抽象出来的。他们执行任务 与传递给线程的类似(事实上,执行 可以包装java.lang.Runnable)。有几个实现是 提供线程池和调度策略。也, 执行结果可以以同步和同步方式获取 异步方式

因此,将简单的可运行线程更改为可调用线程以获取未来变量,并查看如何成功完成该任务:

使用Callable优于Runnable的优点是Callable可以 显式返回一个值


检查这个答案。首先,你要看你通过的第一个文件示例,并说:

以这种方式直接操作线程对于简单的示例来说很好, 但通过并发编程,这样的代码可以很快变得 容易出错,尤其是当多个线程需要协作以 执行更大的任务。在这种情况下,需要修改它们的控制流 协调

因此,在同一份文件中,建议使用执行者:

执行器,它是对普通旧线程的增强,因为 它们是从线程池管理中抽象出来的。他们执行任务 与传递给线程的类似(事实上,执行 可以包装java.lang.Runnable)。有几个实现是 提供线程池和调度策略。也, 执行结果可以以同步和同步方式获取 异步方式

因此,将简单的可运行线程更改为可调用线程以获取未来变量,并查看如何成功完成该任务:

使用Callable优于Runnable的优点是Callable可以 显式返回一个值


检查这个答案,我想你不需要
ForkJoinPool
。您只需使用
倒计时闩锁
。主/父线程将等待
倒计时
0

CountDownLatch latch = new CountDownLatch(2);
Thread t1 = new Thread(() -> {
    // do service call and update the response object 
    latch.countDown();
});
Thread t2 = new Thread(() -> {
    // do database call and update the response object 
    latch.countDown();
});

t1.start();
t2.start();

latch.await(); // main thread will wait here for the completion of T1 & T2 thread. 
编辑:

因此,在线程中以不同的方式处理异常,第一种方式如下,它和我们一样简单异常处理

Thread t1 = new Thread(() -> {
    // do service call
    try {
        // your code here
    } catch (Exception e) {

    }
    latch.countDown();
});
另一种方法是使用新的
Thread.UncaughtExceptionHandler()
,如下所示

Thread.UncaughtExceptionHandler exceptionHandler = new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                //your exception handling code should come here
            }
        };

t1.setUncaughtExceptionHandler(exceptionHandler);

有关线程中异常处理的更多信息,您可以查看我认为您不需要
ForkJoinPool
。您只需使用
倒计时闩锁
。主/父线程将等待
倒计时
0

CountDownLatch latch = new CountDownLatch(2);
Thread t1 = new Thread(() -> {
    // do service call and update the response object 
    latch.countDown();
});
Thread t2 = new Thread(() -> {
    // do database call and update the response object 
    latch.countDown();
});

t1.start();
t2.start();

latch.await(); // main thread will wait here for the completion of T1 & T2 thread. 
编辑:

因此,在线程中以不同的方式处理异常,第一种方式如下,它和我们一样简单异常处理

Thread t1 = new Thread(() -> {
    // do service call
    try {
        // your code here
    } catch (Exception e) {

    }
    latch.countDown();
});
另一种方法是使用新的
Thread.UncaughtExceptionHandler()
,如下所示

Thread.UncaughtExceptionHandler exceptionHandler = new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                //your exception handling code should come here
            }
        };

t1.setUncaughtExceptionHandler(exceptionHandler);

有关线程中异常处理的更多信息,您可以在此处查看您需要的是一个
可完成的未来。虽然其他答案肯定会奏效,
CompletableFuture
s组合得很好。在SpringBoot中也有对它的全面支持;因此,您可以从控制器返回一个
CompletableFuture

你完全可以这样写:

return CompletableFuture.supplyAsync(() -> {
        // call service
        return service.doCall();
 }).thenComposeAsync(result -> {
        // update DB and return original result
        db.update(result);
        return result;
 });
ThenComposeSync()
将确保DB更新将在服务调用后运行


默认情况下,此表达式将在
ForkJoinPool
上运行,但您可以定义它们在哪个
ExecutorService
上运行

您需要的是一个完整的未来。虽然其他答案肯定会奏效,
CompletableFuture
s组合得很好。在SpringBoot中也有对它的全面支持;因此,您可以从控制器返回一个
CompletableFuture

你完全可以这样写:

return CompletableFuture.supplyAsync(() -> {
        // call service
        return service.doCall();
 }).thenComposeAsync(result -> {
        // update DB and return original result
        db.update(result);
        return result;
 });
ThenComposeSync()
将确保DB更新将在服务调用后运行


默认情况下,此表达式将在
ForkJoinPool
上运行,但您可以定义它们在哪个
ExecutorService
上运行

请你再解释一下“按我想要的顺序执行”我所做的是在查询数据库的行上放置一个断点,然后首先执行新的线程部分。一旦调用完成并更新响应,我将释放DB上的线程