工作中用Java做过两三个项目了,大概两年多了,涉及到java线程查资料时偶尔会看到wait,notify,一直不知道能有什么用!直到反编译墨迹天气5.0apk,学习它的背景动画框架时,发现有用的!所以一狠心,网上查了半天资料。今天突然感觉wait notify能应用于自己开发的项目中。写出来记录下!
需求是这样子的:项目是android光伏客户端,里边涉及到公司门户、商城、监控、运维几块。监控界面需要一分钟刷新次实时数据,从java web后台取。所以在FragmentMonitorPage监控fragment中开了一个线程,一分钟取次数据。
以下是最初的做法,为了在关闭屏幕、按home键、弹出其他acitivity期间能节省CPU、电量、网络流量(加过输出调试,在这期间,线程体依然进入,即意味着要消耗CPU时间等资源),需要暂停数据刷新线程的执行,当时在网上没找到好的暂停线程办法,只能每次在onstop时停止线程,onStart时重新new,start线程。总感觉这样子不太好。
以下是原来的代码:
public class FragmentMonitorPage extends BaseFragment implements OnClickListener
{
public static String TAG = FragmentMonitorPage.class.getSimpleName();
…
//数据刷新线程
private boolean mLiveFlag;
private Thread mThreadRealData = null;
@Override
public void onStart()
{
mLiveFlag = true;
mThreadRealData = new Thread(new MyRealDataFreshThread());
mThreadRealData.start();
super.onStart();
}
@Override
public void onStop()
{
mThreadRealData.interrupt();
mLiveFlag = false;
super.onStop();
}
//取实时数据线程
private class MyRealDataFreshThread implements Runnable
{
public void run ()
{
try
{
while (mLiveFlag)
{
if (MyApp.getIsLogin() && MyApp.getCurSubstId() >= 0)
{
//http获取实时数据,一分钟一次
String realdata_result = HttpClientHelper.loadSubstGeneralRealData(Integer.toString(MyApp.getCurSubstId()));
if (!realdata_result.equals(""))
{
//JSON字符串转为对象
substRealDataEntity = JSON.parseObject(realdata_result, SubstRealDataEntity.class);
//发送消息更新UI
Message message = new Message();
message.what = 0;
mFreshHandler.sendMessage(message);
}
}
Thread.sleep(60000);
}
}
catch (InterruptedException e)
{
Log.d("MyRealDataFreshThread", "thread Interrupt");
}
}
}
//UI刷新Handler
private Handler mFreshHandler = new MyHandler(this);
private static class MyHandler extends Handler
{
private final WeakReference< FragmentMonitorPage > mFragment;
public MyHandler(FragmentMonitorPage fragment)
{
mFragment = new WeakReference< FragmentMonitorPage >(fragment);
}
@Override
public void handleMessage(Message msg)
{
switch (msg.what) {
case 0:
//更新当前Fragment实时数据
if (mFragment.get() != null) mFragment.get().freshSubstGeneralRealData(mFragment.get().substRealDataEntity);
break;
}
super.handleMessage(msg);
}
};
在学习了反编译的墨迹天气动画框架后,发现有用到wait notify的,没看懂,网上查了半天资料!突然发现貌似可以解决我上边的问题,于是今天试验了一把。
这是修改后的代码(只列出更改后的):
public class FragmentMonitorPage extends BaseFragment implements OnClickListener {
public static String TAG = FragmentMonitorPage.class.getSimpleName();
…
//数据刷新线程
private boolean mLiveFlag;
private Thread mThreadRealData = null;
private ThreadNotify threadNotify = null;
//定义一个锁定对象
class ThreadNotify
{
public Boolean waitflag = false;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
threadNotify = new ThreadNotify();
//初始启动
mLiveFlag = true;
mThreadRealData = new Thread(new MyRealDataFreshThread());
mThreadRealData.start();
}
@Override
public void onStart()
{
try
{
synchronized (threadNotify)
{
if (threadNotify.waitflag)
{
threadNotify.waitflag = false;
//唤醒阻塞在threadNotify变量上的某一线程,本例中只有一个
threadNotify.notify();
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
super.onStart();
}
@Override
public void onStop()
{
try
{
synchronized (threadNotify)
{
threadNotify.waitflag = true;
}
}
catch (Exception e)
{
e.printStackTrace();
}
super.onStop();
}
//数据刷新线程,加了些输出,测试线程在关闭屏幕、Home键、弹出其他activity时是否暂停了
private class MyRealDataFreshThread implements Runnable
{
public void run ()
{
try {
while (mLiveFlag)
{
Log.d("线程wait notify测试", "线程进入…");
synchronized (threadNotify)
{
if (threadNotify.waitflag == true) weatherThreadNotify.wait();
Log.d("线程wait notify测试", "线程运行中...");
if (MyApp.getIsLogin() && MyApp.getCurSubstId() >= 0)
{
//http获取实时数据,一分钟一次
String realdata_result = HttpClientHelper.loadSubstGeneralRealData(Integer.toString(MyApp.getCurSubstId()));
if (!realdata_result.equals(""))
{
//JSON字符串转为对象
substRealDataEntity = JSON.parseObject(realdata_result, SubstRealDataEntity.class);
//发送消息更新UI
Message message = new Message();
message.what = 0;
mFreshHandler.sendMessage(message);
}
}
}
Thread.sleep(60000);
}
}
catch (Exception e)
{
Log.d("MyRealDataFreshThread", "thread Exception exit");
}
}
}
不知道还有其他办法没,暂时这么用吧!