我在一个程序中编写了一个简单的NIO服务器和内部客户端(在同一程序中),以便服务器从外部接收数据,而内部客户端将服务器接收的数据发送到服务器外部。我使用While()循环在两个并行线程中连续运行这两个进程。现在问题是,我将以非常高的速度向Inside服务器和我收到的所有内容接收数据,我将使用Inside客户端将它们发送到外部服务器。有时,从Buffer中检索数据导致总字符串的一半大小。这意味着我收到“HELLO”,但总字符串是“HELLO SERVER”。这只是一个例子。我会收到很长的字符串。类似地,在通过内部客户端将数据发送到外部服务器之后,我将监听数据并且我正在接收相同的半字符串。我有什么方法可以消除这些半字符串并获得全长字符串。我必须毫不失败地获得完整的字符串。
我正在为进程使用while循环。这使得CPU利用率高达50%。有没有什么办法可以在不使用Thread.sleep方法的情况下降低CPU利用率?因为我需要不断收听外方的数据。他们可能会为一个请求发送2-4个字符串。我尝试使用Executor服务线程连续运行进程,但它需要包含一些睡眠。如果我包含一些睡眠,我无法获得字符串,如果我不包括睡眠,我的CPU利用率将非常高(50-60%)。有谁可以帮我解决这两个问题?
这是我的代码:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_my_books, container, false);
final ListView booksIdListView = (ListView) view.findViewById(R.id.booksIdListView);
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference databaseReference = database.getReference();
final FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
String UID = user.getUid();
databaseReference.child("books").child(UID).addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
final List<String> booksId = new ArrayList<String>();
for (DataSnapshot child: dataSnapshot.getChildren()) {
String userBookId = child.getKey();
booksId.add(userBookId);
}
ArrayAdapter<String> myBooksAdapter = new ArrayAdapter<String>(getActivity() ,
android.R.layout.simple_list_item_1 , booksId);
booksIdListView.setAdapter(myBooksAdapter);
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
答案 0 :(得分:1)
让我们假设您的服务器在每个字符串后附加消息结束标记字符串,例如"<EOM>"
,然后对代码进行以下修改(将其视为草图,因为我没有完全验证它)可以用来等待完整的字符串:
String end = "<EOM>";
StringBuilder curStr = new StringBuilder();
int numRead = 0;
while(-1 != (numRead = channel.read(buffer))){
curStr.append(new String(buffer.array(), 0, numRead, Charset.forName("UTF-8")));
int endIdx = curStr.indexOf(end);
if (endIdx != -1) {
fromOMSqueue.add(curStr.substring(0, endIdx + end.length()));
break;
}
}
if (numRead == -1) {
Socket socket = channel.socket();
SocketAddress remoteAddr = socket.getRemoteSocketAddress();
System.out.println("Connection closed by client: " + remoteAddr);
channel.close();
return;
}
String msg = fromOMSqueue.poll();