2017-10-08 13 views
-1

私は、Javaの同期メソッドが一度に1つの実行であると思っていました。 しかし、2つの呼び出し可能コードが同期ブロックを通過すると、並列実行されていることがわかります。Java Callablesが同期していない

固定スレッドプールを使用した私のExecutorクラスです。

public class ThreadExecutor 
{ 

    ExecutorService executors = Executors.newFixedThreadPool(100); 
    public void callCallable2() 
    { 
     System.out.println("Inside executor callable 2 method"); 
     ThreadTestCallable2 t = new ThreadTestCallable2(); 
     executors.submit(t); 
     System.out.println("Exiting executor callable 2 method"); 
    } 

    public void callCallable1() 
    { 
     System.out.println("Inside the executor callable 1 method"); 
     ThreadTestCallable1 t = new ThreadTestCallable1(); 
     executors.submit(t); 
     System.out.println("exiting the executor callable 1 method"); 
    } 

} 

私の呼び出し可能なクラスは次のとおりです。

public class ThreadTestCallable1 implements Callable { 

    @Override 
    public Object call() throws Exception { 
     System.out.println("Inside the threadtestcallable 1"); 
     ThreadHelperTest t = new ThreadHelperTest(); 
     t.test(); 
     System.out.println("Exiting the threadtestcallable 1"); 
     return null; 
    } 

} 

public class ThreadTestCallable2 implements Callable{ 

    @Override 
    public Object call() throws Exception { 
     System.out.println("Inside the threadtestcallable 2"); 
     ThreadHelperTest t = new ThreadHelperTest(); 
     t.test(); 
     System.out.println("exitting the threadtestcallable 2"); 
     return null; 
    } 


} 

マイ呼び出し可能synchronizeメソッドは、ヘルパークラスです。

public class ThreadTest { 

    public static void main(String arg[]){ 

     ThreadExecutor t = new ThreadExecutor(); 
     t.callCallable1(); 
     t.callCallable2(); 
    } 

} 

上記の実行のための最終的な出力は、私は両方の呼び出し可能が発生しないはずの時間に同期する方法、入る見ている、と何か問題:ここで

public class ThreadHelperTest 
{ 
    public void test() 
    { 
     test1(); 
    } 

    public synchronized void test1() 
    { 
     try { 
      System.out.println("Sleeping for 10 sec's T-name: "+ 
      Thread.currentThread().getName()); 
      Thread.sleep(60000); 
      System.out.println("wokeup T-Name: "+ 
      Thread.currentThread().getName()); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 
} 

は私のメインクラスですオブジェクトを監視しますか?

上記のコードの結果をご覧ください:何を変更する必要がある場合

Inside the executor callable 1 method 
exiting the executor callable 1 method 
Inside executor callable 2 method 
Inside the threadtestcallable 1 
Exiting executor callable 2 method 
Inside the threadtestcallable 2 
Sleeping for 10 sec's T-name: pool-1-thread-1 
Sleeping for 10 sec's T-name: pool-1-thread-2 
wokeup T-Name: pool-1-thread-1 
Exiting the threadtestcallable 1 
wokeup T-Name: pool-1-thread-2 
exitting the threadtestcallable 2 

が私を提案してください。 これらのメソッドを同期させるには

+0

ここでは、新しいオブジェクトを作成して、2つのオブジェクトの2つの異なるモニタを作成することが問題だと思われます。 その場合は、呼び出し可能コード間の同期を達成するための代替案を提案してください。 –

+0

'ThreadTestCallable1'と' ThreadTestCallable2'は 'ThreadHelperTest t'フィールドを持たなければなりません。その後、呼び出し可能ファイルを作成し、 'ThreadHelperTest'の同じインスタンスを渡します。 – luk2302

+0

ここでの問題は、確かに**複数のThreadHelperTestインスタンスがあることです。ルールは、非静的な 'synchronized'が同じインスタンスの他の' synchronized'呼び出し*に対して除外を提供するというものです。あなたは異なるインスタンスを持っています。したがって、相互排除はなく、同期のない/関係の前に発生します。 –

答えて

0

それぞれの呼び出し可能ファイルのインスタンスは、それぞれThreadHelperTestです。異なるインスタンスのsynchronized methodへのコールは、インターリーブすることができます。まず

は、それがにインターリーブする同じオブジェクト synchronizedメソッドの2つの呼び出しのためには不可能です。

ThreadHelperTestの同じインスタンスを呼び出し可能なものに渡すことも、他の共有ミューテックスを使って同期することもできます。

+0

Util.Concurrent.Locks ..を使用する可能性はありますか? これらの2つのコールバック間の同期を達成するために必要なことは何ですか? どのような考えですか? 私は実際にロック機構も試してみましたが、それらも動作していません。スタティックフィールドを使って同期する考えはありますか? –

+0

@AnilkumarPVVすべてが答えです。あなたは本当に 'java.util.concurrent.locks'を必要とせず、単に何かを共有するだけです。 – lexicore

関連する問題