Java 使用数据库DAO类方法获取的相同值的多个线程
Java 使用数据库DAO类方法获取的相同值的多个线程,java,database,multithreading,postgresql,concurrency,Java,Database,Multithreading,Postgresql,Concurrency,状态:已解决 我必须制作一个粘贴盒,因为我必须指出行号 注意:不使用executorsService或线程池。只是要了解以这种方式启动和使用线程的错误如果我使用1个线程。该应用程序工作完美 相关链接: main应用程序, 日志 我通过实例化一个runnable类在for循环中启动了许多线程(10),但似乎我从db得到了相同的结果(我从db获得了一些字符串,然后对其进行了更改),但通过每个线程,我得到了相同的字符串(尽管每个线程都更改了它)。对于postgresql使用jdbc,通常会出现什么
状态:已解决
我必须制作一个粘贴盒,因为我必须指出行号
注意:不使用executorsService或线程池。只是要了解以这种方式启动和使用线程的错误如果我使用1个线程。该应用程序工作完美强>
相关链接:
main应用程序,
日志
我通过实例化一个runnable
类在for循环中启动了许多线程(10),但似乎我从db
得到了相同的结果(我从db获得了一些字符串,然后对其进行了更改),但通过每个线程,我得到了相同的字符串(尽管每个线程都更改了它)。对于postgresql
使用jdbc
,通常会出现什么问题
line 252
and line 223
链接被标记为已处理。(正确)
以db为单位。爬虫类的其他线程也这样做。所以当第252行时
应该得到一个链接。它应该是processed=false
。但我看到所有线程都采用相同的链接。
当其中一个线程对链接进行爬网时。它使它被处理=真。其他人就不应该爬了。(获取它)是否标记为processed=true
getNonProcessedLinkFromDB()
返回未处理的链接
public String getNonProcessedLink(){ line 645
public boolean markLinkAsProcesed(String link){ line 705
getNonProcessedLinkFromDB
将查看是否存在已处理=错误的链接,并给出其中一个链接<代码>限制1
每个线程的起始间隔为20秒。
在一个线程内。1或2秒(估计爬行的处理时间)
如果您看到结果。一个线程使它成为现实。还有一些人可以访问它。过了一段时间就可以了。
所有的线都是分开的。即使是一个种族
。当第一个线程处理链接时,db使链接成为真的这不是一个简洁的问题。里面有很多代码,你根本不知道发生了什么。你需要把它分解,这样你才能理解哪里出了问题,然后给我们展示一下
一些潜在冲突的事情
- 您正在为几乎每个进程打开一个数据库连接。应用程序的正常流程是打开几个连接,进行一些处理,然后关闭它们
- 您正在处理数据库提交吗?我不记得postres数据库的默认设置是什么,您必须查看它
- 一个url有三种状态。未处理的,正在处理的,正在处理的。我认为您根本没有处理“正在处理”状态。因为处理过程需要时间并且可能会失败,所以您必须考虑这些情况
我没有读日志,因为它们对我没用
-编辑以供评论-
数据库通常有事务。您在一个事务中所做的修改在提交之前不会在其他事务中看到。事务可以回滚。您需要查看如何获取刚刚更新的行,并查看值是否真的发生了更改。在其他事务或其他连接中执行此操作
20秒的间隔似乎只有在流程启动时才会出现。设想一种情况,Thread1处理URL1和Thread2处理URL2。他们两个差不多同时完成。它们都查找下一个未处理的URL(例如URL3)。他们都会开始处理这个Url,因为他们不知道另一个线程已经启动了它。您需要一个进程来分发Url,您可能希望看到的是一个队列
如果您知道哪些线程正在处理哪些URL,日志记录可能会得到改进。你还需要一个较小的样本量,这样你就可以了解正在发生的事情。尽管帮助者在这篇文章中的评论和回应也是正确的
在crawl()方法体的开头
synchronized(Crawler.class){
url = getNonProcessedLinkFromDB();
new BasicDAO().markLinkAsProcesed(url);
}
在crawl()方法体的底部(当它完成处理时):
实际上解决了这个问题
将已处理的链接标记为true与获取新链接之间存在着差距,而当前线程正在处理该链接时,其他线程可以获取相同的链接。
同步块
进一步帮助
感谢帮手。IRC频道上的“Fuber”。Quakenet服务器#java和Freenode服务器##javaee
还有所有支持我的人 您正在使用相同的数据库连接吗?我使用newbasicdao().method()
我也尝试将这些方法设置为静态的。或者将它们的调用放入一个同步化块
,或者使布尔值
返回为volatile
。但是没有用。谢谢回复!!!我提到了与该问题相关的确切行号。完整的代码是必要的,以便分析,如果你想。1.多个连接不会造成伤害。这就是DBs的用途。2.db提交是什么意思?你是说postgres使用缓存
?我理解你。但是每个线程在开始时有20秒的间隔。抓取一个页面(处理它)大约需要1到5秒钟。@MasoodAhmad尝试阅读数据库中的事务。它是commit
和rollback
的用途。在不知道事务如何工作的情况下,您将无法构建多线程DB应用程序(因为事务是数据库处理并发性的一种方式),多亏了编辑。我做了和你在日志粘贴中说的一样的事情。它显示URL。2.我知道你刚才说的。我甚至在crawl()
的start
处将链接设置为processed=true
,只是为了确保它在处理开始之前就被标记为processed
。(即线程拥有链接,其他线程应将其视为进程)。还是。。。。。。sa
synchronized(Crawler.class){
url = getNonProcessedLinkFromDB();
new BasicDAO().markLinkAsProcesed(url);
}
crawl(nonProcessedLinkFromDB);