3つの異なる方法で1つのインスタンスに対して3つのメソッドを実行しようとしています。具体的にはThreads
です。つまり、は、methodB
とmethodB
の前に呼び出され、methodC
の前に呼び出される必要があります。奇妙なマルチスレッドの振る舞い
Iは最初のコードで洗練されていないアプローチを試みた:
public void testFoo()
{
Foo foo = new Foo();
ExecutorService service = Executors.newFixedThreadPool(3);
service.submit(() -> foo.callMethodB());
service.submit(() -> foo.callMethodC());
service.submit(() -> foo.callMethodA());
service.shutdown();
}
class Foo
{
boolean methodAcompleted;
boolean methodBcompleted;
void callMethodA()
{
this.methodA();
methodAcompleted = true;
}
void callMethodB()
{
while (true)
{
if (methodAcompleted)
{
this.methodB();
methodBcompleted = true;
break;
}
}
}
void callMethodC()
{
while (true)
{
if (methodBcompleted)
{
this.methodC();
break;
}
}
}
void methodA()
{
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Method A completed!");
}
void methodB()
{
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Method B completed!");
}
void methodC()
{
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Method C completed!");
}
}
私は次の奇数の観察に来た:のみ"Method A completed!"
がプリントアウトされた上記のようなコードを実行
1)。ブール変数をstatic
に変更しても同じ結果が得られます。 2)私はvolatile
にブール変数を変更する場合は、すべてのステートメントが正しい順序で印刷されています?私の知る限りそれが保証(または不可能れていないので、これは、期待されている知っているように
"Method A completed!"
"Method B completed!"
"Method C completed!"
)Thread
こと同じインスタンス上で別のThread
アクションによって変更が通知されます。変数がstatic
の変数で実行されたとしても同じですか?
3)私は彼らがとして実行持つメソッドから遅延Thread.sleep()
を削除するとき、それは奇妙次のようになります。この場合
void methodA()
{
System.out.println("Method A completed!");
}
void methodB()
{
System.out.println("Method B completed!");
}
void methodC()
{
System.out.println("Method C completed!");
}
文がケース2のように正しい順序で常に印刷されています
"Method A completed!"
"Method B completed!"
"Method C completed!"
Thread
と同じではないThread
の変更を参照できますか?volatile
変数? case 1
とcase 3
の異なる動作/結果についての説明は何ですか?
アップデート:私はatomic types
の目的があることが説得しています
class Foo {
AtomicBoolean methodAcompleted = new AtomicBoolean(false);
AtomicBoolean methodBcompleted = new AtomicBoolean(false);
...
}
:
私は、上記のアプローチが不可欠であれば、最善の解決策としてAtomicBoolean
代わりのプリミティブを使用することだと思いますそのような場合に一貫した行動を保証する。