我有我的UI和其他Thread,其中有循环:
while(true){
}
我正在检查系统中String值的更改,当更改时,我通过预先打开的套接字向服务器发送消息。问题是,当应用循环时,我的应用程序冻结,CPU负载非常高(约90%)。我知道,无限循环不能在线程中完成,但是你知道如何复制这种行为,而不是使用无限循环吗?
THX
主要代码(onCreate方法):
mProgressDialog = ProgressDialog.show(main.this, "loading","loading", true);
c=new Client(this.getApplicationContext(), "192.168.0.121", 3333);
c.start();
CLIENT_MESSAGE="login user2 user2";
synchronized(c){
c.notify();
}
Client.zHandler.setEmptyMessage(119);
mHandler = new Handler()
{
public void handleMessage(android.os.Message msg)
{
super.handleMessage(msg);
switch (msg.what)
{
case 11:
Log.d("Logged in", "login");
mProgressDialog.dismiss();
break;
case 12:
Log.d("Logged out", "logout and end");
mProgressDialog.dismiss();
finish();
break;
}
}
};
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
CLIENT_MESSAGE="logout";
synchronized (c) {
c.notify();
}
Client.zHandler.setEmptyMessage(129)
break;
default:
}
return true;
}
线程代码(Client.java):
public Client(Context ctx, String hostname, int port){
this.ctx=ctx;
this.hostname=hostname;
this.port=port;
zHandler = new Handler()
{
public void handleMessage(android.os.Message msg)
{
super.handleMessage(msg);
switch (msg.what)
{
case 119://login
Log.d("119", "case 119");
messageText=DropboxFileClientActivity.CLIENT_MESSAGE;
main.mHandler.sendEmptyMessage(11);
break;
case 129://logout
messageText=DropboxFileClientActivity.CLIENT_MESSAGE;
main.mHandler.sendEmptyMessage(12);
break;
case 100:
break;
}
}
};
}
public void run(){
try {
clientSocket = new Socket(hostname, port);
//inputLine = new BufferedReader(new InputStreamReader(System.in));
os = new ObjectOutputStream (clientSocket.getOutputStream());
is = new ObjectInputStream(clientSocket.getInputStream());
}
catch (UnknownHostException e) {
Log.d("ERROR", "unknown host "+hostname);
}
catch (IOException e) {
Log.d("ERROR2", "no bind"+hostname);
e.printStackTrace();
}
while (!isInterrupted()) {
try{
synchronized (this) {
wait();
}
} catch (InterruptedException e) {
break; // interrupting the thread ends it
}
if (clientSocket != null && os != null && is != null &&!messageText.equals("")) {
messageText="";
//sending message to server, getting reply and displaying it to the screen
}
}//endwhile loop
}
答案 0 :(得分:7)
如果您的循环确实是在一个单独的线程中运行,那么问题是它是一个CPU占用。
不是轮询以检查String
值的更改,而是编写一个从另一个线程触发服务器更新的setter会更好(如果您可以控制相关代码)(使用,比方说,wait
/ notify
协议。
即使您必须进行轮询,您是否真的需要以CPU速度进行轮询?或许一秒一次会做什么?那会让你在剩下的时间里睡觉。
至少,每次循环都要调用Thread.yield()
。
编辑根据您对帖子的评论,您应该在后台线程中等待:
在你的后台主题中:
while (!isInterrupted()) {
synchronized (this) {
wait();
} catch (InterruptedException e) {
break; // interrupting the thread ends it
}
// read string and send it to the server
}
在您的事件处理程序中:
public void onSomethingHappened(...) {
// update the string
synchronized (mThread) {
mThread.notify();
}
}
除非在同一对象上同步读取和更新,否则应将字符串标记为volatile。
答案 1 :(得分:1)
否则
synchronized(blah){
blah.wait();
}
是旧的同步方式。查看java.util.concurrent包中的一些类。
一个例子是,在你的活动中你可以实现/添加一个TextWatcher,你可以在方法中
blockingQueue.put(theChangedText) //preferably you would do the put via an access method.
然后在你的主题中你会粗略地说:
obj = blockingQueue.take()
sendToServer(obj)