2013-10-12 77 views
0

我目前想實現應用程序與機器溝通,並應主要工作如下:循環屏障重用?

  • 程序將消息發送到服務器(在這種情況下,第一個255個字節的文件)。
  • 機器以「成功接收消息」或「接收消息錯誤 」響應作出響應。
  • 根據機器的響應,程序必須決定是否發送下一條消息(下一個255字節)或不是(最後一條消息的錯誤,必須重新開始)。
  • 等等程序需要發送的每條消息(取決於文件的大小)。

所以,我們認爲有一個線程來做發送,另一個做接收,因爲我們有一個API來註冊一個類作爲從機器接收消息的類(只需通過實現一個接口),並且將消息發送到機器的方法不是阻塞類型,所以等待機器響應的方法,以便程序可以決定在響應到達後要執行什麼操作。

因此,我們需要以某種方式同步這兩個線程,因爲可以確定他們將交換多少條消息,這使我們嘗試了一個CyclicBarrier。這是用於測試的CyclicBarrier是否會幫我們解決這個問題的代碼(程序實際上並未使用插座與機器溝通,這只是用於測試的屏障):

import java.io.*; 
import java.net.*; 
import java.util.concurrent.*; 

public class BlockingTest{ 
    private CyclicBarrier barrier; 

    class Receiver implements Runnable{ 
    @Override public void run(){ 
     try{ 
     ServerSocket ss = new ServerSocket(8080); 
     while(!barrier.isBroken()){ 
      System.out.println("Waiting message..."); 
      Socket response = ss.accept(); 
      BufferedReader br = new BufferedReader(new InputStreamReader(
       response.getInputStream())); 
      System.out.printf("Received: %s\n", br.readLine()); 
      barrier.await(); 
     } 
     }catch(InterruptedException | BrokenBarrierException | 
     IOException ex){ 
     System.err.println(ex.getMessage()); 
     } 
    } 
    } 

    public BlockingTest(){ 
    this.barrier = new CyclicBarrier(2, new Runnable(){ 
     @Override public void run(){ 
     System.out.println("done."); 
     } 
    }); 

    new Thread(new Receiver()).start(); 

    try{ 
     Socket sender = new Socket("localhost", 8080); 
     PrintWriter pw = new PrintWriter(sender.getOutputStream(), true); 
     for(int i = 0; i < 3; i++){ 
     System.out.println("Sending message:"); 
     pw.println("Message!"); 
     this.barrier.await(); 
     } 
    }catch(InterruptedException | BrokenBarrierException | IOException ex){ 
     System.err.println(ex.getMessage()); 
    } 
    } 

    public static void main(String[] arg){ 
    new BlockingTest(); 
    } 
} 

此代碼工作如果我們只發送一條消息(BlockingTest()構造函數中的塊爲no,只是發送消息),但在添加for塊之後,它無法按預期工作。它只能是第一次,那麼它掛起:

Waiting message... 
Sending message: 
Received: Message! 
done. 
Waiting message... 
Sending message: 

的問題是:

  • 如何使屏障可重用?是自動的還是它有 手動完成?

  • 由於我錯過了插座(或屏障代碼),程序是否掛起?

+0

由於發送和接收是按順序完成的,所有工作都可以在單線程中完成。兩個線程是不必要的複雜和浪費資源。 –

+0

我是這麼認爲的,但是我們遇到了一些問題,試圖使它成爲順序的,因爲標記爲接收消息的對象通過一個硬件中斷來通知傳入消息,而我們無法控制這個硬件中斷,程序等待機器的響應,所以有時會丟失信息;在我們的例子中是不可接受的,因爲這些文件實際上是用於智能卡芯片的操作系統。 –

+0

你在說什麼硬件中斷?你顯示的文本只使用標準的Socket和ServerSocket用法。然後,在測試中,單一屏障用於客戶端和服務器線程。實際上,客戶端和服務器運行在不同的進程中,並且不能訪問同一個對象。 –

回答

0

它掛起的原因是,你打開一個連接到服務器,並保持數據發送給它,但在接收端,你丟棄的第一個連接,並開始等待下一次連接即將發生。

您可以在每次發送數據時從發件人創建新的連接。代碼塊

Socket sender = new Socket("localhost", 8080); 
PrintWriter pw = new PrintWriter(sender.getOutputStream(), true); 

必須在for循環內移動。 (當然,照顧釋放所有資源)

OR,

固定接收器從第一連接讀取數據,而不是等待數據的第二組一個新的連接。

+0

不錯... :)現在它可以工作(程序根本不會掛起,而是等待消息)。但是當你說「修復接收機從第一個連接讀取數據」時,你是什麼意思? –

+0

即移動「Socket response = ss.accept(); BufferedReader br = new BufferedReader(new InputStreamReader(response.getInputStream()));」在while循環之外,並且繼續讀取來自該連接的下一行數據。 – srkavin