2009-04-03 28 views
8

Vì vậy, tôi có hai chủ đề.Chủ đề PrintWriter của socket Java có an toàn không?

Chủ đề quản lý kết nối máy khách. (Chỉ có một khách hàng và một máy chủ)
Tôi gọi đó là chuỗi máy chủ của tôi.

Thread two quản lý việc gửi tin nhắn cho khách hàng. Tôi gọi nó là chuỗi xử lý tin nhắn của tôi.

Chủ đề chịu trách nhiệm, trong số những thứ khác gửi nhịp tim cho khách hàng theo định kỳ.

Khi lập trình tôi giả định rằng các ổ cắm không an toàn, nhưng các bộ đệm, và miễn là tôi đang sử dụng bộ đệm riêng biệt cho máy chủ và các bộ xử lý, tôi sẽ ổn.

Tôi cũng đưa ra giả định rằng "PrintWriter" tương tự như bộ đệm socket trong Java.

Theo các giả định này tôi đã viết chức năng này để gửi một nhịp tim:

public void sendHeartBeat(){ 
     logger.info("Sending a hearbeat!"); 
     PrintWriter printWriter=null; 
     try { 
      printWriter = new PrintWriter(clientSocket.getOutputStream()); 
     } catch (IOException e) { 
      logger.info(e.toString()); 
     } 
     if(printWriter!=null){ 
      printWriter.print("HEARTBEAT#"); 
      printWriter.flush(); 
     } 
    } 

Các chủ đề khác, "xử lý" một điều gì đó tương tự ở chỗ nó:

printWriter=new PrintWriter(theServer.getClientSocket().getOutputStream()); 

Theo cách này Tôi sẽ tạo ra một "bộ đệm" mới mỗi khi tôi muốn gửi một nhịp tim, và các tin nhắn của tôi sẽ không bao giờ bị ghi đè.

Thật không may điều này dường như không đúng. Và tôi nhận được một tin nhắn đến qua đường ống như sau: dsgdsbHEARTBEAT # sdg

Điều này gây ra một kết xuất cốt lõi sau đó.

Dưới đây là những câu hỏi của tôi:

1) Sockets rõ ràng là không đề an toàn, nhưng là PrintWriters tôi nhận được từ họ chủ đề an toàn? Hay là nó chỉ trả về cùng một PrintWriter?

2) Tương tự như bộ đệm socket trong Java là gì? Tôi nên suy nghĩ như thế nào về vấn đề này?

3) Làm cách nào để làm cho các chuỗi này không ghi vào cùng một bộ đệm trên ổ cắm?

Trả lời

10

Thiết kế kém để có nhiều số PrintWriter giây này trên cùng một luồng. Thực sự bạn muốn ít nhất là đối tượng gọi chúng được đồng bộ (hoặc thread giới hạn).

Tuy nhiên, giả sử vì một lý do bạn làm điều muốn nhiều PrintWriter s:

Vấn đề đầu tiên: Writer s không sử dụng this như khóa. PrintWriterBufferedWriter theo mặc định, cả hai đều sử dụng Writer chúng được tạo bằng khóa. Điều này rõ ràng là hoàn toàn bị hỏng. Họ nên sử dụng khóa của Writer, không phải là bản thân Writer.Một sai lầm dễ dàng cho rằng việc khóa một tính năng của Object sẽ loại bỏ an toàn kiểu tĩnh. Vì vậy, bạn sẽ cần phải xây dựng một PrintWriter với ổ cắm OutputStream (hoặc một số đối tượng phổ biến khác) làm khóa.

Thứ hai, chúng tôi có bộ đệm trong phạm vi PrintWriter. Vì vậy, đến cuối của một bộ đệm, một nửa có được bằng văn bản và một nửa chờ đợi cho việc viết tiếp theo. Để ngăn chặn điều đó, hãy khóa bên ngoài để kết hợp một số printflush hoặc sử dụng tính năng tự động xả và thêm ký tự dòng mới.

Vì vậy, nó không phải là có nghĩa là an toàn chỉ nhưng bạn có thể hack nó. Hoặc bạn có thể sử dụng một thiết kế tốt hơn.

+0

Tôi đã xem xét Java SE 1.6.0_31 src cho việc này. 'PrintWriter (Writer out)' cuối cùng gọi là 'Writer được bảo vệ (Object lock)' và ở đó, 'Writer' gán 'khóa' này vào 'khóa' bên trong được sử dụng trong 'Writer' để đồng bộ hóa. Vì vậy, bạn có thể pl. giải thích tại sao bạn nghĩ khóa bị hỏng ở đây? – shrini1000

+0

@ shrini1000 'PrintWriter' gọi' Writer (Object lock) 'với' super (out); '. Vì vậy, 'lock' là' out', thay vì 'out.lock'. (Đây là vấn đề triển khai - đặc điểm kỹ thuật dường như bị thiếu.) –

+0

Điều này dường như vẫn xảy ra trong Java 8 - PrintWriter gọi super (out) và khóa bị tắt thay vì out.lock. –

4

Bạn cần một cách để sử dụng cùng một PrintWriter giữa các chủ đề (t1.writer == t2.writer, không chỉ PrintWriter s được tạo từ cùng một OutputStream). Với cùng một PrintWriter, tất cả các thao tác ghi được đồng bộ hóa.

+1

Bạn đang nói rằng PrintWriters là chủ đề an toàn, nhưng OutputStreams thì không? – Alex

+3

Tôi nghĩ rằng Chris nói rằng PrintWriter là thread-an toàn, nhưng hai trên cùng một dòng không có nghĩa là thread-an toàn. Do đó sử dụng một. –

Các vấn đề liên quan