2017-07-07 7 views
0

をマルチスレッド使用して通話同期(通知)は、Javaの後に動作していません。コードは、私はこれを読んでいた

コンシューマは、リストにオブジェクトが格納されているサーバーです。このリストの追加/削除ができます。

プロデューサは、プロデューサが停止していない場合、Consumer Serverがオブジェクト(整数)を格納している場合にのみ、データを送信します(PipedInputStream/PipedOutputStream)。サーバに再びオブジェクトがあると、プロデューサはデータの送信を開始します。

問題

は、私は次のメソッドを呼び出すときに、上げ

public void addInteger() { 
     new Thread (new Runnable() { 
     public void run() { 
      try { 
      System.out.println ("Add before size:" + lConsumerClient.size()); 
      lConsumerClient.add((int)(Math.random()*100.0)); 
      synchronized(oSignalExternal) { 
       oSignalExternal.notify(); 
      } 
      System.out.println ("Add after size:" + lConsumerClient.size()); 
      } catch (Exception e) { e.printStackTrace(); } 
     } 
     }).start(); 
    } 

    public void removeFirst() { 
     new Thread (new Runnable() { 
     public void run() { 
      try { 
      System.out.println ("Remove before size:" + lConsumerClient.size()); 
      if (hasInteger()) { 
       lConsumerClient.remove(0); 
      } 
      synchronized(oSignalExternal) { 
       oSignalExternal.notify(); 
      } 
      System.out.println ("Remove after size:" + lConsumerClient.size()); 
      } catch (Exception e) { e.printStackTrace(); } 
     } 
     }).start(); 
    } 

出力:

Add before size:0 
Add after size:1 
     i:0 ->18 =218 
     i:0 ->18 =218 
Add before size:1 
     i:0 ->18 =218 
     i:1 ->90 =290 
     i:0 ->18 =218 
     i:1 ->90 =290 
Add before size:2 
     i:0 ->18 =218 
     i:1 ->90 =290 
     i:2 ->76 =276 
Add before size:3 
     i:0 ->18 =218 
     i:1 ->90 =290 
     i:2 ->76 =276 
     i:3 ->43 =243 
Remove before size:4 
Remove before size:3 
Remove before size:2 
     i:0 ->43 =243 
     i:0 ->43 =243 
Remove before size:1 
ExtSynchro$ExtClient sleeping 
Remove after size:0 
Remove after size:0 
Remove after size:0 
ExtSynchro$ExtClient sleeping 
Add after size:0 
Add after size:0 
Add after size:0 
Remove after size:0 

待機して働いている通知します。

私は、コールの後に理由を知りたい:

synchronized(oSignalExternal) { 
    oSignalExternal.notify(); 
} 

んが、コードが実行されませんか?あなたのexConsumerServerは常に要素を持っているので、ここで

完全なコード

import java.awt.*; 
import java.awt.event.*; 
import java.io.*; 
import java.util.*; 
import java.util.concurrent.BlockingQueue; 
import java.util.concurrent.ArrayBlockingQueue; 

import javax.swing.*; 
public class ExtSynchro extends JFrame { 

    JButton jbSync = new JButton("Sync"); 
    JButton jbPlus = new JButton("+"); 
    JButton jbMinus = new JButton("-"); 
    JButton jbStop = new JButton("Stop"); 

    Object oSignalExternal = new Object(); 
    ExtServer exConsumerServer; 
    ExtClient exProducerClient; 
    PipedInputStream pSnk = new PipedInputStream(); 
    PipedOutputStream pSrc = new PipedOutputStream(); 
    static final String NL = System.getProperty("line.separator"); 

    public ExtSynchro() { 
    setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 

    jbSync.addActionListener((ActionEvent e) -> { 
     try { pSrc.connect(pSnk); } catch (IOException ex) {} 
     exConsumerServer = new ExtServer(); 
     exProducerClient = new ExtClient(); 
     exConsumerServer.start(); 
     exProducerClient.start(); 
    }); 

    jbPlus.addActionListener((ActionEvent e) -> { 
     exConsumerServer.addInteger(); 
    }); 

    jbMinus.addActionListener((ActionEvent e) -> { 
     exConsumerServer.removeFirst(); 
    }); 

    jbStop.addActionListener((ActionEvent e) -> { 
     exConsumerServer.stopThread(); 
     exProducerClient.stopThread(); 
     exConsumerServer = null; 
     exProducerClient = null; 
    }); 

    JPanel jpButtons = new JPanel(); 
    jpButtons.setLayout(new BoxLayout(jpButtons, BoxLayout.PAGE_AXIS)); 
    jpButtons.add(jbSync); 
    jpButtons.add(jbPlus); 
    jpButtons.add(jbMinus); 
    jpButtons.add(jbStop); 
    add(jpButtons); 
    pack(); 
    } 

    public static void main(String args[]) { 
    EventQueue.invokeLater(() -> { 
     new ExtSynchro().setVisible(true); 
    }); 
    } 

    class ExtClient extends Thread { 
    private volatile boolean bRunning; 

    @Override public void run() { 
     bRunning = true; 
     while (bRunning) { 
     try { 
      synchronized(oSignalExternal) { 
      try { 
       while (exConsumerServer.hasInteger()) { 
       pSrc.write(200); 
       try { Thread.sleep(3000); } catch (InterruptedException ex) { } 
       } 
       System.out.println(getClass().getName() + "\tsleeping"); 
       oSignalExternal.wait(); 
      } catch (InterruptedException e2) {} 
      if (!bRunning) break; // To exit from synchronized 
      } 
     } catch (IOException e) { 
      bRunning = false; 
     } 
     } 
     System.out.println(getClass().getName() + "\tfinishing"); 
    } 

    public void stopThread() { 
     bRunning = false; 
     synchronized(oSignalExternal) { 
     oSignalExternal.notify(); 
     } 
    } 
    }; 

//The Consumer Server. 

    class ExtServer extends Thread { 
    private volatile boolean bRunning; 
    //BlockingQueue<Integer> lConsumerClient =new ArrayBlockingQueue<>(10); 
    java.util.List<Integer> lConsumerClient = Collections.synchronizedList(new ArrayList<>(4)); 


    @Override public void run() { 
     bRunning = true; 
     while (bRunning) { 
     int iRd; 
     try { 
      while ((iRd = pSnk.read()) != -1) { 
      for (int i = 0; i < lConsumerClient.size(); i++) { 
       int n = lConsumerClient.get(i); 
       System.out.println ("\t\ti:" + i + " ->" + n +"\t=" + (n + iRd)); 
      } 
      } 
     } catch (IOException e) {} 
     } 
     System.out.println(getClass().getName() + "\tfinishing"); 
    } 

    public void addInteger() { 
     new Thread (new Runnable() { 
     public void run() { 
      try { 
      System.out.println ("Add before size:" + lConsumerClient.size()); 
      lConsumerClient.add((int)(Math.random()*100.0)); 
      synchronized(oSignalExternal) { 
       oSignalExternal.notify(); 
      } 
      System.out.println ("Add after size:" + lConsumerClient.size()); 
      } catch (Exception e) { e.printStackTrace(); } 
     } 
     }).start(); 
    } 

    public void removeFirst() { 
     new Thread (new Runnable() { 
     public void run() { 
      try { 
      System.out.println ("Remove before size:" + lConsumerClient.size()); 
      if (hasInteger()) { 
       lConsumerClient.remove(0); 
      } 
      synchronized(oSignalExternal) { 
       oSignalExternal.notify(); 
      } 
      System.out.println ("Remove after size:" + lConsumerClient.size()); 
      } catch (Exception e) { e.printStackTrace(); } 
     } 
     }).start(); 
    } 

    public boolean hasInteger() { 
     return lConsumerClient.size() > 0; 
    } 
    public void stopThread() { 
     bRunning = false; 
     try { pSrc.close();pSnk.close(); } catch (IOException e) {} 
    } 
    }; 
} 
+4

これは、あなたが読んでくれると期待している非常にたくさんのコードです。それを[mcve]に切り落としてください。 –

+2

また、 "私は初心者です"し、wait()とnotify()から離れてください。あなたが何をしているのかを知っていれば素晴らしいことができますが、正しく使うのは難しいです。これらを(実際にはほとんどのマルチスレッディングで)残しておけば、Javaのはるかに強固な理解が得られるでしょう。 (私は正直言って、私は本当のためにこれを使う必要はなかったと言うことができます: 'java.util.concurrent'の高水準クラスは*多く*使いやすくなりました)。 –

+0

メインはなく、カット&ペーストは何を達成するのですか? – matt

答えて

0

このセクションでは、あなたのコード

synchronized(oSignalExternal) { 
     try { 
     while (exConsumerServer.hasInteger()) { 
      pSrc.write(200); 
      try { Thread.sleep(3000); } catch (InterruptedException ex) { } 
     } 
     System.out.println(getClass().getName() + "\tsleeping"); 
     oSignalExternal.wait(); 
     } catch (InterruptedException e2) {} 
     if (!bRunning) break; // To exit from synchronized 
    } 

を破るあなたは、要素を削除しないでください。ブロッキングキューを使用します。

BlockingQueue<Integer> valuesToTake = new LinkedBlockingQueue(); 

あなたの実行方法は次のようになります。

while (bRunning) { 
    try{ 
     pSrc.write(valuesToTake.take()); 
    } catch (IOException e) { 
     bRunning = false; 
    } 
} 

次に、取得する値に整数を書き込むだけで、クライアントがそれらを送信します。

+0

@Anita EDTで整数が追加されていて、アプリケーションをブロックしています。あなたはEDTのその行動を実行する必要があります。キューを使用するのはこのためです。あなたはエグゼキュータにアクションを提出するか、それをキューに投稿し、対応するスレッドがそれを処理します。 – matt

+0

ありがとう、今私は問題を理解しています。このため、私は質問を変更しました。 'BlockingQueue'と' LinkedBlockingQueue'を確認しています。保存されているすべてのオブジェクトを確認するために 'ValuesStored.peek(Index)'のようなものはありません。オブジェクト... 'take()' ... – Anita

関連する問題