Handler概念
Handler允许你发送和处理Message和Runnable object通过关联的一个线程的MessageQueue.
Handler线程间传递消息机制
调用示例1
主函数
myThread = new MyThread();
Message message = mHandler.obtainMessage();
message.what = 1;
mHandler.sendMessage(message);
线程类 MyThread
线程类一创建,就会实例化MyHandler,线程创建后使用start(),线程就启动了吗?
private class MyThread{
public MyThread() {
final HandlerThread thread =
new HandlerThread("myThread",
Thread.MIN_PRIORITY);
thread.start();
mHandler = new MyHandler(thread.getLooper());
}
private class MyHandler extends Handler{
public MyHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case 1:
try {
Log.i(TAG, "handleMessage: " + msg.what);
String str = URLDecoder.decode(msg.obj.toString(), "UTF-8");
Log.d(TAG, "handleMessage: " + str);
} catch (Exception e) {
Log.e(TAG,e.getMessage());
e.printStackTrace();
}
break;
}
}
}
}
测试结果
2023-04-04 20:31:22.181 28448-32076/cn.jj.restart I/JJWorld: handleMessage: 1
2023-04-04 20:31:22.181 28448-32076/cn.jj.restart E/JJWorld: Attempt to invoke virtual method 'java.lang.String java.lang.Object.toString()' on a null object reference
线程间通信 Handler与读写锁对比1
Handler每秒传输120次消息 通过读写锁每秒传输120次消息对比。
RandomStringUtils工具类来自于此库 implementation ‘org.apache.commons:commons-lang3:3.7’
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private MyThread myThread;
private Handler mHandler;
private String TAG = "JJWorld";
private Button button;
private int interval = 0;
private int interval2 = 0;
private ArrayList<String> list = new ArrayList<String>();
private ArrayList<String> list2 = new ArrayList<String>();
private ReentrantReadWriteLock readWriteLock =new ReentrantReadWriteLock();
private Button button2;
private Integer period = 8;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myThread = new MyThread();
Message message = mHandler.obtainMessage();
message.what = 1;
message.obj = 1;
mHandler.sendMessage(message);
initView();
button.setOnClickListener(this);
button2.setOnClickListener(this);
}
private void initView() {
button = (Button) findViewById(R.id.button);
button2 = (Button) findViewById(R.id.button2);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button:
new Timer().schedule(new TimerTask() {
@Override
public void run() {
interval++;
Message message = mHandler.obtainMessage();
message.what = 1;
message.obj = interval + RandomStringUtils.random(15);
mHandler.sendMessage(message);
}
}, 0, period);
break;
case R.id.button2:
new Timer().schedule(new TimerTask() {
@Override
public void run() {
try {
readWriteLock.writeLock().lock();
list2.add(String.valueOf(interval2++ + RandomStringUtils.random(15)));
if (list2.size() >= 60){
Message message = mHandler.obtainMessage();
message.what = 2;
message.obj = list2;
mHandler.sendMessage(message);
}
}catch (Exception e){
}finally {
readWriteLock.writeLock().unlock();
}
}
}, 0, period);
break;
}
}
private class MyThread {
public MyThread() {
final HandlerThread thread =
new HandlerThread("myThread",
Thread.MIN_PRIORITY);
thread.start();
mHandler = new MyHandler(thread.getLooper());
}
private class MyHandler extends Handler {
public MyHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 1:
try {
list.add(msg.obj.toString());
if (list.size() >= 60) {
Log.d(TAG, "list: " + list);
list.clear();
}
} catch (Exception e) {
Log.e(TAG, e.getMessage());
e.printStackTrace();
}
break;
case 2:
try {
readWriteLock.readLock().lock();
Log.d(TAG, "list: " + list2);
list2.clear();
} catch (Exception e) {
Log.e(TAG, e.getMessage());
e.printStackTrace();
}finally {
readWriteLock.readLock().unlock();
}
break;
}
}
}
}
}
结论
使用读写锁CPU使用率稳定于 0%-1%;
使用Handler进行传输消息,CPU使用率稳定与 1%-2%;
Handler
读写锁
线程间通信 Handler与读写锁对比2
handler和锁方式性能消耗接近。
加锁情况下,创建两个线程分别每4ms修改一次NotNeedCollectData中的userId与game_scene参数,创建两外一个线程每20ms读取一次NotNeedCollectData中的userId与game_scene,CPU使用率大约为2%-3%;
使用Hanler进行消息传递,创建两个线程分别每4ms传递一次userId与game_scene参数,创建两外一个线程每20ms读取一次userId与game_scene,CPU使用率大约为3%;
测试程序如下:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private MyThread myThread;
private Handler mHandler;
private String TAG = "JJWorld";
private Button button4;
private Button button5;
private Button button;
private Button button2;
private Button button3;
private NotNeedCollectData notNeedCollectData;
private int period = 4;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myThread = new MyThread();
Message message = mHandler.obtainMessage();
message.what = 1;
message.obj = 1;
mHandler.sendMessage(message);
initView();
button4.setOnClickListener(this);
button5.setOnClickListener(this);
notNeedCollectData = new NotNeedCollectData();
button.setOnClickListener(this);
button2.setOnClickListener(this);
button3.setOnClickListener(this);
}
private void initView() {
button4 = (Button) findViewById(R.id.button4);
button5 = (Button) findViewById(R.id.button5);
button = (Button) findViewById(R.id.button);
button2 = (Button) findViewById(R.id.button2);
button3 = (Button) findViewById(R.id.button3);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button4:
mHandler.sendEmptyMessage(4);
break;
case R.id.button5:
mHandler.sendEmptyMessage(5);
break;
case R.id.button:
new Timer().schedule(new TimerTask() {
@Override
public void run() {
notNeedCollectData.setUserid("time:" + String.valueOf(System.currentTimeMillis()));
}
}, 0, period);
new Timer().schedule(new TimerTask() {
@Override
public void run() {
notNeedCollectData.setGame_scene("scene:" + String.valueOf(System.currentTimeMillis()));
}
}, 0, period);
break;
case R.id.button2:
new Timer().schedule(new TimerTask() {
@Override
public void run() {
Message message = mHandler.obtainMessage();
message.what = 6;
message.obj = String.valueOf(System.currentTimeMillis());
mHandler.sendMessage(message);
}
}, 0, period);
new Timer().schedule(new TimerTask() {
@Override
public void run() {
Message message = mHandler.obtainMessage();
message.what = 7;
message.obj = String.valueOf(System.currentTimeMillis());
mHandler.sendMessage(message);
}
}, 0, period);
break;
case R.id.button3:
mHandler.sendEmptyMessage(8);
break;
}
}
private class MyThread {
public MyThread() {
final HandlerThread thread =
new HandlerThread("jjThread",
Thread.MIN_PRIORITY);
thread.start();
mHandler = new MyHandler(thread.getLooper());
}
private String time;
private String scene;
private Runnable runnable = new Runnable() {
@Override
public void run() {
mHandler.postDelayed(this, period * 5);
Log.i(TAG, "time:" + notNeedCollectData.getUserid() + " scene:" + notNeedCollectData.getGame_scene());
}
};
private Runnable runnable2 = new Runnable() {
@Override
public void run() {
mHandler.postDelayed(this, period * 5);
Log.i(TAG, "time:" + time + " scene:" + scene);
}
};
private class MyHandler extends Handler {
public MyHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 4:
mHandler.post(runnable);
break;
case 5:
mHandler.removeCallbacks(runnable);
break;
case 6:
time = (String) msg.obj;
break;
case 7:
scene = (String) msg.obj;
break;
case 8:
mHandler.post(runnable2);
break;
default:
}
}
}
}
}
结果
Handler性能消耗 3%左右
锁性能消耗 2-3%左右
HandlerThread与Thread的区别
HandlerThread 内部实现了 Looper,不用再调用Looper.prepare()和Looper.loop()这些方法。
Thread需要手动调用Looper.prepare()和Looper.loop()方法。
Handler循环定时执行任务
mHandler.sendEmptyMessageDelayed(4,2000) 方式
使用mHandler.sendEmptyMessage(4)
与mHandler.sendEmptyMessageDelayed(4,2000)
可以实现程序的循环执行,但是无法终止程序。
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private MyThread myThread;
private Handler mHandler;
private String TAG = "JJWorld";
private Button button4;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myThread = new MyThread();
Message message = mHandler.obtainMessage();
message.what = 1;
message.obj = 1;
mHandler.sendMessage(message);
initView();
button4.setOnClickListener(this);
}
private void initView() {
button4 = (Button) findViewById(R.id.button4);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button4:
mHandler.sendEmptyMessage(4);
break;
}
}
private class MyThread {
public MyThread() {
final HandlerThread thread =
new HandlerThread("jjThread",
Thread.MIN_PRIORITY);
thread.start();
mHandler = new MyHandler(thread.getLooper());
}
private class MyHandler extends Handler {
public MyHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 4:
Log.i(TAG, "time: " + System.currentTimeMillis());
mHandler.sendEmptyMessageDelayed(4,2000);
break;
}
}
}
}
}
mHandler.post(runnable) 方式
通过
mHandler.post(runnable)
以及mHandler.removeCallbacks(runnable)
实现代码的循环与重启。
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private MyThread myThread;
private Handler mHandler;
private String TAG = "JJWorld";
private Button button4;
private Button button5;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myThread = new MyThread();
Message message = mHandler.obtainMessage();
message.what = 1;
message.obj = 1;
mHandler.sendMessage(message);
initView();
button4.setOnClickListener(this);
button5.setOnClickListener(this);
}
private void initView() {
button4 = (Button) findViewById(R.id.button4);
button5 = (Button) findViewById(R.id.button5);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button4:
mHandler.sendEmptyMessage(4);
break;
case R.id.button5:
mHandler.sendEmptyMessage(5);
break;
}
}
private class MyThread {
private Runnable runnable = new Runnable() {
@Override
public void run() {
mHandler.postDelayed(this, 2000);
// TODO Auto-generated method stub
Log.i(TAG, "thread " + Thread.currentThread().getName());
//要做的事情,这里再次调用此Runnable对象,以实现每两秒实现一次的定时器操作
Log.e(TAG, "case 4:" + System.currentTimeMillis());
}
};
public MyThread() {
final HandlerThread thread =
new HandlerThread("jjThread",
Thread.MIN_PRIORITY);
thread.start();
mHandler = new MyHandler(thread.getLooper());
}
private class MyHandler extends Handler {
public MyHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 4:
mHandler.post(runnable);
break;
case 5:
mHandler.removeCallbacks(runnable);
break;
}
}
}
}
}
Timer开启循环任务
Timer本身会开启线程:
new Timer().schedule(new TimerTask() {
@Override
public void run() {
notNeedCollectData.setUserid("time:" +String.valueOf(System.currentTimeMillis()));
}
}, 0, period);