0

我正在创造多个未来,我希望只有一个能够实现预期目标。

如何从未来中取消所有其他期货?

这就是我创建期货的方式:

jobs = days_to_scan.map{|day|
      Concurrent::Future.execute do
        sleep_time = day.to_f / days_to_scan.count.to_f * seconds_to_complete.to_f        
        sleep (sleep_time)
        if GoogleAPI.new.api_call(@adwords, ad_seeder, visitor, day) 
           # How to cancel other futures here?
        end
      end
    }
4

2 回答 2

1

我可能会迟到,但无论如何我都会回复,因为其他人可能会偶然发现这个问题。

所以你想要的是可能在一个 Future 完成后立即强制关闭线程池:

class DailyJobs
  def call
    thread_pool = ::Concurrent::CachedThreadPool.new
    jobs = days_to_scan.map{ |day|
      Concurrent::Future.execute(executor: thread_pool) do
        sleep_time = day.to_f / days_to_scan.count.to_f * seconds_to_complete.to_f        
        sleep (sleep_time)
        if GoogleAPI.new.api_call(@adwords, ad_seeder, visitor, day) 
           # How to cancel other futures here?
           thread_pool.kill
        end
      end
    }
  end
end

问题是:实际上并不推荐杀死线程池,并且可能会产生不可预测的结果

更好的方法是跟踪 Future 何时完成并忽略其他 Futures:

class DailyJobs
  def call
    status = ::Concurrent::AtomicBoolean.new(false)

    days_to_scan.map{ |day|
      Concurrent::Future.execute do
        return if status.true? # Early return so Future does nothing

        sleep_time = day.to_f / days_to_scan.count.to_f * seconds_to_complete.to_f        
        sleep (sleep_time)
        if GoogleAPI.new.api_call(@adwords, ad_seeder, visitor, day)
          # Do your thing
          status.value = true # This will let you know that at least one Future completed
        end
      end
    }
  end
end

值得注意的是,如果这是一个 Rails 应用程序,您可能希望包装您的 Future on Rails 执行程序以避免自动加载和死锁问题。我在这里写了

于 2021-04-21T11:00:38.923 回答
0

好的,我可以将其实现为:

#wait until one job has achieved the goal
while jobs.select{|job| job.value == 'L' }.count == 0 && jobs.select{|job| [:rejected, :fulfilled].include?(job.state) }.count != jobs.count   
    sleep(0.1)  
end
#cancel other jobs    
jobs.each{|job| job.cancel unless (job.state == :fulfilled && job.value == success_value) }    
}    

于 2020-12-17T14:43:43.607 回答