java - Java/Tomcat 多线程(?)问题中的 RESTful 服务

标签 java multithreading rest tomcat

我用 Java 编写的 RESTful 服务消耗大量小文件(大约 300 字节),将它们写入磁盘,将它们作为 BLOB 插入到 Oracle 数据库中,最后删除它们。 为了防止由于网络中断或其他原因而丢失文件,如果磁盘上有多个文件,我必须将它们写入磁盘以批量插入。

我的问题是:如果我通过 cURL 和 Windows-batch 运行连续的 POST 请求,一切都会按预期无限期地工作,每秒大约 3-5 个文件。

如果我创建另一个批处理来对服务器/服务进行基准测试,一些文件会被双重插入到数据库中。

它是这样工作的:POST 请求(八位字节流)-> RESTful 服务 [-> 检查有效文件 -> 写入磁盘 -> 目录扫描器将目录中的所有 *.XYZ 文件读入字符串数组 -> 插入数据库 -> 如果插入成功:删除文件。

我相信由于我的服务的多线程性质,如果在某个时间跨度(比如:几毫秒)处理两个请求,两个线程的插入过程将同一个文件插入数据库,一个线程删除它们,第一个thread 找不到该文件(因为 thread2 已经删除了它),等等。

我的问题是:如何防止这种情况发生?我开始将所有变量等创建为私有(private)的,这样其他线程就无法访问它们(我相信这就是它的工作原理)。但是在两个(或所有)线程共存的非常有限的时间跨度内,thread2 从 thread1“窃取”文件,但是 AFTERthread1 已经插入了它。

正如您可能推断出的那样,我不是专业的 Java 程序员,所以也许您可以为我指明正确的方向。让我知道您是否需要代码片段或任何东西。


编辑
澄清工作流程: 该服务通过 http POST 获取八位字节数据流到某个 URI /service/{ID}/{file},其中 ID 是一个整数,file 是请求中文件的扩展名。
该服务将文件写入磁盘,然后将文件插入数据库 (BLOB)。
有时文件可能是一个 zip 压缩文件,我必须将其解压缩,然后将解压缩的文件插入到数据库中。
在网络中断的情况下,我无法连接到数据库。这就是为什么我将每个文件写入磁盘,将它们读入字符串数组并在连接再次建立后立即将它们插入数据库的原因。

我认为问题在于,两个线程同时写入两个文件,两个线程都将文件扫描到自己的字符串数组中,两个线程都上传文件。 (<- 这就是我认为我可能错的地方)。 我可以重现这个问题,甚至可以重现 3 或 4 或 5 个 cURL 批处理,然后 3 或 4 或 5 个文件是重复的。

EDIT2(日志示例)

10-Jun-2016 09:56:14.400 SEVERE [pool-275-thread-1] ServiceResource.doSendData array: file1.tst - [Ljava.lang.String;@3107ce05

10-Jun-2016 09:56:14.400 SEVERE [pool-274-thread-1] ServiceResource.doSendData array: file1.tst - [Ljava.lang.String;@6996e2db

最佳答案

好吧,我开始重新编码 directoryscanner 部分。现在我收到文件,如果是 zip 文件,将其解压缩,获取文件头,将它们插入数据库,如果传输正确,最后删除它们。如果没有连接到数据库,文件将写入磁盘,一旦数据库再次联机,就会插入到数据库中。
感谢您的投入,我真的在这里学到了一些东西:)

关于java - Java/Tomcat 多线程(?)问题中的 RESTful 服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37742098/

相关文章:

java - 链表删除方法返回删除的节点和新节点

java - 如何将参数传递给java中已经运行的线程?

java - @JsonIgnore 不适用于 Spring Boot 应用程序

Java png 出来是黑色的

java - 获取所有联系人时出错

python 线程 图形用户界面

c# - WCF Rest api - [WebGet] 工作,但未找到 [WebInvoke(...GET...)] 的端点

ios - Alamofire - 使用照片时图像上传失败

java - MySQL 和 Eclipse 错误

c++ - 安全地取消 boost asio 截止时间计时器