خيوط جافا كود آمن + طريقة سؤال عطومي
-
11-09-2019 - |
سؤال
لدي مدير فئة سيتم الوصول إليها من قبل مؤشرات الترابط متعددة في نفس الوقت، أريد أن أعرف إذا فعلت ذلك بالطريقة الصحيحة؟
وأعتقد أيضا أنني بحاجة إلى refectfoo لتكون ذرية، لكنني لست متأكدا
public class Manager
{
private ConcurrentHashMap<String, Foo> foos;
//init in constructor
public RemoveFoo(String name)
{
Foo foo = foos.Get(name);
foo.RemoveAll();
foos.Remove(name);
}
public AddFoo(Foo foo)
{...}
}
public class Foo
{
private Map<String,Bar> bars;
//intialize it in constructor
//same for RemoveBar
public void AddBar(Bar bar)
{
synchronized(this)
{
bars.put(bar.id, bar);
}
}
public void RemoveAll()
{
synchronized(this)
{
//some before removall logic for each one
bars.remove(bar.id, bar);
}
}
}
public class Bar
{}
المحلول
RemoveFoo
يمكن أن تكون مشكلة. أقترح استخدام:
Foo foo = foos.remove (name);
if (foo != null) foo.removeAll();
في حين أن. هذا يتأكد من أن الخريطة لا تتغير بين get()
و remove()
.
في Foo
, ، يكفي مزامنة bars
بدلا من المثال كله. لكن هذا مجرد تحسين بسيط.
نصائح أخرى
لا تحتاج إلى طرق متزامنة كما كنت تستخدم Concurrenthashmap، ومع ذلك كن على علم بذلك Foo foo = foos.Get(name)
يمكن إرجاع null حيث يمكن بالفعل إزالة مؤشر ترابط آخر الإدخال من الخريطة.
يمكن إعلان الأعضاء كما Map<String, Foo> foos
, ، ولكن يجب الاحتهية foos = new ConcurrentHashMap<String, Foo>;
يعلن RemoveFoo(String)
كما synchronized
:
public synchronized void RemoveFoo(String name) {
…
}
أيضا، أن ينصح بما يلي:
- يجب أن تكون أسماء الأسلوب حالة صغيرة، على سبيل المثال
removeFoo
بدلا منRemoveFoo
. وبعد هذا ليس ج #. :) - كل طريقة تحتاج نوع المرتج:
public removeFoo()
ليس إعلان طريقة صالحة، يجب أن يكونpublic void removeFoo()
.
إذا كنت تستخدم concurrenthmap في فو مثل
private Map<String,Bar> bars = new ConcurrentHashMap<String, Bar>();
ربما يمكنك الاستغناء عن المزامنة في فو كذلك.
لست متأكدا مما ستفعله على Foo وبار، ولكن يبدو وكأنه نمط من الكتب.
إذا لم يتم الرجوع إليها من قبل الآخرين، ما عليك سوى استدعاء FOOS.REMOVE (الاسم)؛ واترك محرك GC يعالج الكتب.