同步方法不断被调用

时间:2011-04-19 14:26:59

标签: java multithreading synchronization

我对多线程仍然有些新意,所以这可能是一个简单的答案,但我尝试使用锁和同步方法进行搜索,但这样做并不正确。

我有一个连接到ftp站点并下载xml文件进行处理的系统。应用程序一直等到ftp站点上的文件更新,如果没有更新,它什么都不做。如果更新,则下载xml文件以开始处理。

在我们处理xml之前,我们检查服务器上的文件版本,以及数据库中某些内容的版本,如果版本不相同,则创建一个新线程并将服务器上的文件更新为新版本。

所以在代码中它几乎就是:

if(file.version.equals(db.version))
{ 
  do work...
}
else 
{
  startUpdateThread();
}

private synchronized void startUpdateThread()
{
   Runnable updateRunnable = new UpdateRunnable();
   Thread updateThread = new Thread(updateRunnable);
   updateThread.start();
}

我遇到的问题是,在更新服务器上的文件的过程中,xml文件将在ftp站点上发生更改并仍然输入startUpdateThread()方法,并且在完成时我将尝试多个线程完成相同的任务。

我的问题是,为什么syncrhonized方法仍然被调用,即使它应该被锁定,如果我做错了什么是正确的方法来解决这个问题而不创建多个线程来完成相同的任务。

修改 对系统的进一步解释,服务器上的文件在应用程序启动时被加载到缓存中,因此file.version.equals实际上来自缓存。该文件只需每隔几个月重新生成一次,这是手动完成的,我将自动完成。

服务器上的文件和xml文件之间没有任何关系,当应用程序看到服务器上的文件发生了变化(大约每两分钟一次)时,就会触发此检查。要生成新文件并将其加载到缓存大约需要10分钟。因此,检查大约发生5次,从而创建5个线程,重新生成文件。

期望的结果是:

继续使用xml文件进行正常处理

正在创建一个新线程来重新加载服务器上的完全独立的文件。

希望这更有意义......

4 个答案:

答案 0 :(得分:1)

当然 - 方法startUpdateThread()是同步的,但不是线程的实际执行。当updateThread.start()调用终止时锁定被释放 - 这在工作线程完成之前很久。

问题是,您期望的行为是什么:如果远程文件在处理过程中发生更改,那么我的理解是,更改的文件具有不同的编号。

您可以向正在运行的工作线程发送信号以停止处理该文件,因为它已经过时。或者你想让“第二”工作线程等到第一个工作线程结束?在这种情况下,大小为1的ThreadPool可以提供帮助。

答案 1 :(得分:0)

我认为你对Java中的并发结构有误解。 startUpdateThread()将启动更新线程并立即返回,因此锁定无用。您可能需要将updateThread存储为字段,并在调用synchronized (this)之前检查startUpdateThread锁定期间是否为空。

答案 2 :(得分:0)

我建议您执行一项检查任务,以及处理/下载的一项或多项任务。

你遇到的问题是很多线程都在同时执行检查,他们都看到需要下载文件,所以他们都调用了startUpdateThread()

解决这个问题的简单方法是同步检查,以便只有一个线程可以执行检查,因为它需要更新。

但是,由于你每次都开始一个新的线程,我不清楚你为什么要在多线程dmanner中调用这个方法。我只想用一个线程进行检查。

显然,在更新时不应再次检查文件。 ;)

我建议你不要每次都启动一个Thread,而是使用ExecutorService来汇集你的线程。

答案 3 :(得分:0)

我在你正在做的事情的逻辑中有点迷失,但我可以告诉你'同步'是如何工作的,然后你可以确保你的逻辑遵循这一点。

当你使一个“普通”实例方法(像这个)同步时,这实际上意味着一次只有一个线程可以在同一个对象上执行任何同步方法。 (或者可以在任何明确同步的objcet代码中。)

我不知道这是否影响你正在做的事情,但请注意我可以按照以下方式开课:

public class MyClass {
  public synchronized void someMethod() {
    ...
  }
}

然后仍然有两个独立的MyClass的实例,每个实例都调用someMethod()在不同的线程中同时运行。另一方面,在MyClass的相同的实例上,我无法同时运行someMethod()两次调用。

如果你使用synchronized有点迷失,那么你也可以考虑使用Java 5中引入的一个显式锁。(如果它有帮助,我在Java 5 Locks上有一些文章,确实在{ {3}}一般在我的网站上你可能想看看。)