Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/70.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 与类或方法相反的围绕变量的同步_Java_Sql_Multithreading_Design Patterns_Synchronization - Fatal编程技术网

Java 与类或方法相反的围绕变量的同步

Java 与类或方法相反的围绕变量的同步,java,sql,multithreading,design-patterns,synchronization,Java,Sql,Multithreading,Design Patterns,Synchronization,在我的场景中,用户向服务器发送请求,然后服务器可以将项目列表上载到数据库。项目列表以for循环的形式上载到数据库,该循环由几个查询组成。按顺序将这些项添加到数据库中是非常重要的 秩序 现在的问题是,如果用户发出另一个请求,将启动另一组for循环,并且这些项可能不会以正确的顺序添加到数据库中。(因为将有两个for循环向数据库添加项) 示例:请求1:1,2,3 请求2:4,5,6 它们插入数据库的顺序: 应为:1,2,3,4,5,6 但是,可能是:1,4,2,5,6,3 如果不同的用户发出请求,则没

在我的场景中,用户向服务器发送请求,然后服务器可以将项目列表上载到数据库。项目列表以for循环的形式上载到数据库,该循环由几个查询组成。按顺序将这些项添加到数据库中是非常重要的 秩序

现在的问题是,如果用户发出另一个请求,将启动另一组for循环,并且这些项可能不会以正确的顺序添加到数据库中。(因为将有两个for循环向数据库添加项)

示例:请求1:1,2,3 请求2:4,5,6 它们插入数据库的顺序: 应为:1,2,3,4,5,6 但是,可能是:1,4,2,5,6,3

如果不同的用户发出请求,则没有问题,因为这两个请求将相互排斥

为了解决这个问题,我可以使用静态方法或使用synchronized关键字,但我不想在代码中造成瓶颈(其他用户不必等待访问数据库!)

或者,使用for循环执行多个查询可能是个坏主意


如何围绕“请求”而不是对象或方法同步代码?是否存在设计模式或其他内容?

您应该在数据库中强制执行事务。无论您执行什么进程内同步,只要您有多个应用程序服务器实例(这在几乎所有非平凡的应用程序中都是如此),您的代码就会中断


例如,您可以在代表用户的行上使用排他行锁。这样,请求将在数据库中序列化,而与您有多少应用程序服务器无关。

听起来您需要将请求排成
队列才能插入数据库。这样,所有查询都将以您需要的顺序形式执行

但是,要正确地执行此操作,您需要在单独的线程中执行此操作(不管如何,这都是一件好事,因为数据库事务通常会阻塞,或者非常缓慢)


这个解决方案不需要“锁”,并且由于线程,仍然会响应,但是将保持您对线性的需求。

< P>如果多个应用服务器不是问题,考虑StripedLock。它允许您在ID上同步,同时只创建有限数量的锁

private static Striped Striped_LOCK=Striped.lazyWeakLock(64);
试一试{
STRIPPED_LOCK.get(id.LOCK();
东西
}最后{
解除锁定。获取(id)。解锁();
}

在您的情况下,您可以使用会话ID(字符串)作为ID。

我们这里没有完整的图片,但由于您说“用户发出另一个请求”,我推测他没有等待第一个请求完成


在这种情况下,你可以考虑一种“命令”模式;查询在放入队列的对象中表示,程序一次处理一个队列外的对象。队列中的每个对象都是一个表示其处理的“命令”。

可能不是最好的,但如果我处于您的情况,我将使用单独的批处理在单独的队列处理中执行

示例:队列和详细信息有两个表:

List_Queue(
    id int identity not null primary key,
    user_id varchar(xx),
    is_processable tinyint default 0,
    is_processing tinyint default 0,
    is_processed tinyint default 0,
)

List_Queue_Detail(
    queue_id int,
    // your rest of data,
    inserted_timestamp datetime
)
每次用户提交时都会插入
列表\u队列
表。那么在您的示例中,队列表中可能有这样的记录:

11, user01, 0, 0
12, user01, 0, 0
您的事务将插入队列详细信息表。它可能按未排序的顺序排列,如:

11, 1, '01.001'
11, 2, '01.021'
12, 4, '01.032'
12, 5, '01.044'
11, 3, '01.055'
12, 6, '01.061'
请注意以秒和毫秒为单位的时间戳。你可以在这里有正常的约会时间

现在,您已经完成了对队列详细信息表的插入。假设您现在处于这种队列状态:

11, user01, 0, 0, 0
12, user01, 1, 0, 0
过程12在过程11之前完成。这是正常情况。现在,您的批处理(可能每分钟执行一次)将获得“is_processed=0的最小队列id”,因此您得到:

11, user01, 0, 0, 0

并且它不处理请求。如果它是可处理的,那么您可以开始将队列详细信息插入到实际事务表中。开始插入时,不要忘了将请求标记为“正在处理”

如果两个列表中的项目以不同的顺序插入,会出现什么问题?好吧,如果列表中的每组项目都有一个基于时间(或由数据库控制)的唯一索引,作为当前事务中处理的数据组的唯一标识符,那就更容易了。您的案例就像一家银行。我可以给一个出纳员多次存款和取款在一次访问窗口。他们按顺序完成。其他人也可以。没有干扰。但如果我妻子和我同时来访,而她的取款在我小额取款之后、大额存款之前出现,我们可能会出现透支的情况。(这不是一个完美的类比。好吧。)我很确定有可能发生干扰。在我的情况下,我会在你之后把存款交给出纳,但另一个出纳会处理我的支票。因此,我的一些存款可能比你的一些存款早完成。实际上,我使用的是命令模式。但是,像这样使用命令模式似乎不是最优雅的解决方案。为什么会这样?因为,我必须为每个用户及其操作保留一个队列。这看起来并不优雅,也不那么易读。显然,数据库内容与用户有关。也许这就是为什么他们不互相干涉。我按顺序添加我的多个条目,你添加你的条目,我们不会冲突,因为它们彼此不相关。仅限于您和我。您的命令对象是否可以包含用户信息,以便处理它时不必从用户上下文中使用它?如果一个用户请求的所有数据库活动都在一个事务中完成,即使存在一个包含许多数据库查询的循环,用户的第二个请求不会干扰,它们将在数据库级别独立执行。比在应用程序容器中执行要好得多。如何执行
11, user01, 0, 0, 0