Java 在同一对象上使用Fork和Join
我正在做一个spring boot项目。我有一个场景,需要进行服务调用,从DB获取数据并更新响应对象。 我希望在两个不同的线程中执行这些操作,以获得更好的性能 我尝试使用以下代码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
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上的线程