Java 如何维护从文件读取的值的缓存? 安装程序

Java 如何维护从文件读取的值的缓存? 安装程序,java,multithreading,scala,caching,Java,Multithreading,Scala,Caching,有一个正在运行的程序正在执行任意计算并将状态(一个整数值,表示进度)写入文件。整数值只能递增 现在我正在开发另一个应用程序,它可以(除其他外)对这些整数值执行算术运算,例如比较。这些文件将被永久删除,并由其他程序写入。因此,不能保证文件在任何时候都存在 基本上,应用程序需要执行一些任意的操作,但对另一个程序的进度有限制,即,只有当另一个程序完成了足够的工作时,它才能执行某些操作 问题 在执行算术运算时,应用程序不应该关心整数值来自何处。特别是,访问这些整数值不能引发异常。我应该如何区分执行io访

有一个正在运行的程序正在执行任意计算并将状态(一个整数值,表示进度)写入文件。整数值只能递增

现在我正在开发另一个应用程序,它可以(除其他外)对这些整数值执行算术运算,例如比较。这些文件将被永久删除,并由其他程序写入。因此,不能保证文件在任何时候都存在

基本上,应用程序需要执行一些任意的操作,但对另一个程序的进度有限制,即,只有当另一个程序完成了足够的工作时,它才能执行某些操作

问题 在执行算术运算时,应用程序不应该关心整数值来自何处。特别是,访问这些整数值不能引发异常。我应该如何区分执行io访问时可能发生的所有不好的事情

请注意,我不希望执行线程阻塞,直到可以从文件中读取值。例如,假设文件系统不知何故死亡,则整数值将不会更新,但主线程仍应继续工作。这种愿望是由算术比较作为谓词的定义驱动的,它有两个结果,正确和错误,但没有第三个“错误”——结果。这就是为什么我认为需要以某种方式缓存从文件中读取的值

限度 Java 1.7,Scala 2.11

当前方法 我有一个解决方案,看起来它会起作用,但我不确定是否会出问题

解决方案是为每个文件维护这些整数值的缓存。核心功能由缓存的getter提供,同时还有一个单独的“updater”线程,该线程不断读取文件并更新chaches

如果发生错误,生产者应注意(即记录错误),但应继续运行,因为不完整的计算不应影响后续计算

我目前正在做的一个最简单的例子如下:

object Application {

  def main(args: Array[String]) {
    val caches = args.map(filename => new Cache(Paths.get(filename))
    val producer = new Thread(new Updater(caches)))
    producer.start()
    execute(caches)
    producer.interrupt()
  }
  def execute(values: Array[AccessValue]) {
    while (values.head.getValue < 5) {/* This should never throw an exception */}
  }
class Updater(caches: Array[Cache]) {
  def run() {
    var interrupted = false
    while(!interrupted) {
      caches.foreach{cache => 
        try {
          val input = Files.newInputStream(cache.file)
          cache.updateValue(parse(input))
        } catch {
          case _: InterruptedException => 
            interrupted = true
          case t: Throwable => 
            log.error(t)
            /*continue as if nothing happend*/
        }
      }
    }
  }
  def parse(input: InputStream): Int = input.read() /* In reality, some xml parsing */
}
trait AccessValue{ 
  def getValue: Int // should not throw an exception
}
class Cache(val file: Path) extends AccessValue{ 
  private val value = 0
  def getValue = value
  def updateValue(newValue: Int) { value = newValue }
}
对象应用程序{
def main(参数:数组[字符串]){
val caches=args.map(文件名=>新缓存(path.get(文件名))
val producer=新线程(新更新程序(缓存)))
producer.start()
执行(缓存)
producer.interrupt()
}
def执行(值:数组[AccessValue]){
while(values.head.getValue<5){/*这永远不会引发异常*/}
}
类更新程序(缓存:数组[缓存]){
def运行(){
var=false
而(!中断){
caches.foreach{cache=>
试一试{
val input=Files.newInputStream(cache.file)
updateValue(解析(输入))
}抓住{
案例:InterruptedException=>
中断=真
案例t:可丢弃=>
日志错误(t)
/*继续,好像什么也没发生一样*/
}
}
}
}
def parse(input:InputStream):Int=input.read()/*实际上,一些xml解析*/
}
特征访问值{
def getValue:Int//不应引发异常
}
类缓存(val文件:Path)扩展了AccessValue{
私有值=0
def getValue=value
def updateValue(newValue:Int){value=newValue}
}
这样做在一个综合测试设置上是可行的,但是我想知道是否会发生一些不好的事情。另外,如果有人用不同的方法处理这个问题,我很高兴听到如何处理

  • 是否有一个可丢弃的线程会导致其他线程失控?我在考虑OutOfMemoryException或StackOverflow。我是否需要以不同的方式处理它们,或者这无关紧要,因为,例如,整个应用程序无论如何都会死掉
  • 如果InterruptException抛出到try块之外,或者甚至在catch块中,会发生什么?有没有更好的方法来终止线程
  • 类缓存的成员值必须声明为volatile吗?我不太关心读写的顺序,但编译器不能因为推断值是常量而“优化”读取值
  • 有很多不同的并发相关库。您是否建议我使用新线程以外的其他库(…).start()?如果是,您建议使用什么工具?我知道Scala的ExecutionContext、Future和Java的Executors类,它们为线程池提供了各种静态构造函数。但是,我以前从未使用过这些工具,也不知道它们的优缺点。我还偶然发现了“Akka”这个名称,但我的猜测是,使用Akka对于我想要实现的目标来说是过分的

谢谢

我建议您通读一下并发

当一个线程写入一个值,而另一个线程读取一个值时,您应该始终使用同步块或将该值声明为volatile。否则,无法保证一个线程写入的值对另一个线程可见(请参阅关于建立发生之前关系的说明)

OutOfMemoryException会影响其他线程,因为OutOfMemoryException引用的堆空间在线程之间共享。StackOverflow异常只会杀死发生它的线程,因为每个线程都有自己的堆栈


如果您不需要两个线程之间的某种同步,那么您可能不需要任何未来或执行器。

这个问题与缓存有什么关系?很难理解您的程序是如何工作的,因此很难推荐解决方案。通过缓存,我指的是整数值是核心程序see的n连续性不必与查找实例中写入文件的值相同