多Java线程中的变量同步
我的问题是如何使用block synchronized,我的类FileAdapter有一个方法write,它接收我下载文件时使用的HTTP连接结果的InputStream,对于下载并写入磁盘的每千字节,它调用它接收的DownloadReport类实例的下载方法,用于传递已下载的内容。 在另一个向用户打印输出的线程中,它调用updateProgress方法(也是DownloadReport类的方法),该方法负责更新终端上显示给用户的进度条。 问题在于,如果FileAdapter类在输出线程尝试更新进度条时尝试更新下载的字节数,因为这两种方法都编辑变量intermediateDownloaded的值,该变量仅作为辅助变量,以保存自上次更新以来下载的字节数,计算下载速度。 如果我在downloaded和updateProgress方法中使用synchronized this块,它将阻止整个类DownloadReport,并且输出线程将只能在FileAdapter类更新下载字节数后更新进度条? 文件适配器:多Java线程中的变量同步,java,multithreading,Java,Multithreading,我的问题是如何使用block synchronized,我的类FileAdapter有一个方法write,它接收我下载文件时使用的HTTP连接结果的InputStream,对于下载并写入磁盘的每千字节,它调用它接收的DownloadReport类实例的下载方法,用于传递已下载的内容。 在另一个向用户打印输出的线程中,它调用updateProgress方法(也是DownloadReport类的方法),该方法负责更新终端上显示给用户的进度条。 问题在于,如果FileAdapter类在输出线程尝试更新
public void write(InputStream content, DownloadReport downloadReport) throws IOException {
FileOutputStream output = new FileOutputStream(file);
byte[] buffer = new byte[1024];
int read;
while ((read = content.read(buffer)) != -1) {
output.write(buffer, 0, read);
downloadReport.downloaded(read);
}
}
下载报告:
public void downloaded(int bytes) {
intermediateDownloaded += bytes;
downloaded += bytes;
}
public void updateProgress() {
long now = System.currentTimeMillis();
double delta = UnitHelper.sizeRound(((now - lastTimeUpdate) / 1000.0), 2);
if (delta >= 1) {
unitAdapter.convertSpeed(intermediateDownloaded, delta);
intermediateDownloaded = 0;
lastTimeUpdate = now;
}
progressBar.updateProgress(unitAdapter.finalSize,
unitAdapter.recalculate(downloaded), unitAdapter.unity);
}
首先,这种类型的同步在最近十年或更长的时间里已经失去了吸引力,因为: 要把它做好是非常困难的 由于等待,它的性能受到影响 这是不稳定的。 使用这种方法,您的代码中可能总是有bug,可能会导致竞争条件,您可能不知道,并且您无法编写单元测试来确保您的代码不受竞争条件的影响。线程间通信的现代方法是使用消息队列传递不可变消息 现在,如果你坚持这样做,同步这是一个坏主意,因为谁持有对你的对象的引用,谁也可以同步你的对象,然后你就死锁了。同步方法也是如此,因为编译器在后台使用同步方法来实现它们。所以,也不要这样做。始终声明要用作锁的私有对象 此外,正如您似乎已经了解的,同步锁需要尽可能少地处于活动状态,以避免阻塞可能也需要获取该锁的其他线程。因此,它需要包装尽可能少的指令 对于您的代码,如果我理解正确,您需要执行以下操作:
private final Object lock = new Object();
public void downloaded( int bytes )
{
synchronized( lock )
{
downloaded += bytes;
}
}
然后再往下看,无论何时访问下载的文件,都必须与lock同步,并且需要找到其他方法来计算仅基于下载的文件的下载变量,以便它不需要参与同步。非常感谢您的帮助,但我不明白为什么不在synchronized内部使用它,它会阻止所有具有此类实例的线程吗?@Rafael F N Xavier你应该尝试使用一个私有对象作为同步块的锁,现在,如果您使用公共属性,那么在您的类之外可能有一些代码可以在公共属性上同步,从而导致死锁情况。“this”也是如此,可能有代码超出了类的代码,将同步块放在当前对象上。现在这又会导致deadlock@nits.kk谢谢,读了你的评论,重读了迈克·纳基斯的回答,我现在明白了这个问题。