线程安全的易失性关键字(Volatile keyword for thread safety)
我有以下代码:
public class Foo { private volatile Map<String, String> map; public Foo() { refresh(); } public void refresh() { map = getData(); } public boolean isPresent(String id) { return map.containsKey(id); } public String getName(String id) { return map.get(id); } private Map<String, String> getData() { // logic } }
- 以上代码线程是安全的还是我需要在那里添加
synchronized
或互斥? 如果它不是线程安全的,请澄清原因。另外,我已经读过应该使用
AtomicReference
而不是这个,但是在AtomicReference
类的源代码中,我可以看到用于保存该值的字段是易变的(以及一些便捷方法)。
- 是否有使用
AtomicReference
的特定原因?我已经阅读了与此相关的多个答案,但volatile的概念仍然让我感到困惑。 提前致谢。
I have the below code:
public class Foo { private volatile Map<String, String> map; public Foo() { refresh(); } public void refresh() { map = getData(); } public boolean isPresent(String id) { return map.containsKey(id); } public String getName(String id) { return map.get(id); } private Map<String, String> getData() { // logic } }
- Is the above code thread safe or do I need to add
synchronized
or mutexes in there? If it's not thread safe, please clarify why.Also, I've read that one should use
AtomicReference
instead of this, but in the source of theAtomicReference
class, I can see that the field used to hold the value is volatile (along with a few convenience methods).
- Is there a specific reason to use
AtomicReference
instead?I've read multiple answer related to this but the concept of volatile still confuses me. Thanks in advance.
原文:https://stackoverflow.com/questions/45216390
最满意答案
在某些时候,你必须有一个特定的
K
和V
此时,您将需要(隐式)范围中的隐式读者,在此之前,您可以隐式传递它们:def getMap[K, V](js: JsValue, key: String)(implicit reads: Reads[Map[K,V]]): Map[K, V] = { js \ key match { case JsDefined(v) => v.as[Map[K, V]] // error here case _: JsUndefined => throw new Exception("Error") } }
我不知道为什么你会这样设置它。 为什么不这样做
(js \ key).as[Map[K,V]]
如果你想要它抛出错误或者(js \ key).asOpt[Map[K,V]]
如果一个Option也可以。 或者,也可以(js \ key).validate[Map[K,V]]
At some point you will have to have a specific
K
andV
. At that point you will need the implicit readers in (implicit) scope, until then, you can just implicitly pass them:def getMap[K, V](js: JsValue, key: String)(implicit reads: Reads[Map[K,V]]): Map[K, V] = { js \ key match { case JsDefined(v) => v.as[Map[K, V]] // error here case _: JsUndefined => throw new Exception("Error") } }
I am not sure why you would set it up this way though. Why not do either
(js \ key).as[Map[K,V]]
if you want it to throw an error or(js \ key).asOpt[Map[K,V]]
if an Option is ok as well. Or, also possible(js \ key).validate[Map[K,V]]
相关问答
更多-
你的代码对我有用。 我唯一做的就是这一行: implicit val reads = Json.reads[Environment] Your code worked for me. The only thing I've done is put this line: implicit val reads = Json.reads[Environment]
-
使用tryAccept返回兑换时的未来结果或错误: def socketTest = WebSocket.tryAccept[JsValue] { request => futureJsonVariable.map { json => val in = Iteratee.ignore[JsValue] val out = Enumerator(json).andThen(Enumerator.eof) Right((in, out)) } recover { case ...
-
或者使用像Play for Scala-book的Twitter示例中那样隐含的val-stuff更好? 是的,对于经典转换,这是一个很好的解决方案(简单而简洁)。 但是有一种更简单的方法可以通过“ Json Macro Inception ”实现这种转换: import play.api.libs.json._ import play.api.libs.functional.syntax._ case class File(name: String, size: Long) implicit val f ...
-
播放:如何验证JsValue(Play: How to validate a JsValue)[2023-06-24]
根据我的理解,验证器的功能不是转换JSON,而是验证它是否具有某些字段并且它们是预期的类型。 如果要转换JSON以删除“垃圾”,您可以: userValidator.reads(user).map(js => js - "trash") 或仅包括某些字段: userValidator.reads(user).map(js => Json.obj("name" -> js \ "name", "email" -> js \ "email")) 你可能已经看过这篇文章,但是它非常有用我还是把它包括在内。 B ... -
object Inventory { implicit def fmt[T <: Item](implicit fmt: Format[T]): Format[Inventory[T]] = new Format[Inventory[T]] { def reads(json: JsValue): Inventory[T] = new Inventory[T] ( (json \ "blah").as[String] ) def writes(i: Inventory[ ...
-
JsValue表示任何类型的JSON数据实体,包括对象,数字,字符串等。 如果要在JsObject中过滤值,则必须将JsValue“转换”为JsObject。 喜欢: val jsonObject: JsObject = response.as[JsObject] 然后你可以改变对象的喜好。 阅读有关JsObject和JsValue的文档,了解如何完成剩下的尝试。 https://www.playframework.com/documentation/2.5.x/api/scala/index.html#p ...
-
在某些时候,你必须有一个特定的K和V 此时,您将需要(隐式)范围中的隐式读者,在此之前,您可以隐式传递它们: def getMap[K, V](js: JsValue, key: String)(implicit reads: Reads[Map[K,V]]): Map[K, V] = { js \ key match { case JsDefined(v) => v.as[Map[K, V]] // error here case _: Js ...
-
值键不是play.api.libs.json.JsValue的成员(value keys is not a member of play.api.libs.json.JsValue)[2023-06-23]
Json.parse生成一个JsValue ,它可以表示任何类型的json对象(布尔值,数字,数组等)。 如果您知道自己正在使用对象,则可以使用.as[JsObject] : import play.api.libs.json._ val result = Json.parse(jsonStr).as[JsObject] println("key: " + result.keys.head) Json.parse produces a JsValue, which could represent any ... -
你够近了。 用这个: val js = Json.obj("numbers" -> JsObject(numbers)) 输出: js: play.api.libs.json.JsObject = {"numbers":{"one":1,"two":2,"three":3}} Json.obj是构造Json.obj的快捷方式,在你的情况下它不是那么方便。 You were close enough. Use this: val js = Json.obj("numbers" -> JsObject(nu ...
-
Play Framework:类型不匹配JsValue / JsValueWrapper(Play Framework: type mismatch JsValue / JsValueWrapper)[2023-05-01]
这是解决方案: def toProjection(json: JsValue) = { json.getOpt(__ \ "matchItem").map { value => val obj = value.as[JsObject] for (key <- obj.keys) { obj.getOpt(__ \ key).map { matchObj => for (matchKey <- matchObj.as[JsObject].keys) { matchObj.get ...