Looper分析。ThreadLocal有关
Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one,
call prepare() in the thread that is to run the loop, and then loop() to have it process messages until the loop is stopped.
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
(1)提出问题:正如上面所说, 一个线程默认是没有Looper用来处理message队列的。但为什么我们在主线程时又没有自己创建Looper呢?
public class Looper {
private static final String TAG = "Looper";
// sThreadLocal.get() will return null unless you've called prepare().
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>(); //(1)又见到了眼熟的ThreadLocal,里面存放的是每个线程的Looper
private static Looper sMainLooper; // guarded by Looper.class
final MessageQueue mQueue;
final Thread mThread;
volatile boolean mRun;
private Printer mLogging;
/** Initialize the current thread as a looper.
* This gives you a chance to create handlers that then reference
* this looper, before actually starting the loop. Be sure to call
* {@link #loop()} after calling this method, and end it by calling
* {@link #quit()}.
*/
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
/**
* Initialize the current thread as a looper, marking it as an
* application's main looper. The main looper for your application
* is created by the Android environment, so you should never need
* to call this function yourself. See also: {@link #prepare()}
*/
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper(); //(2)为主线程的Looper赋值
}
}
/** Returns the application's main looper, which lives in the main thread of the application.
*/
public static Looper getMainLooper() {
synchronized (Looper.class) {
return sMainLooper;
}
}
/**
* Return the Looper object associated with the current thread. Returns
* null if the calling thread is not associated with a Looper.
*/
public static Looper myLooper() { //(3)为主线程Looper赋值的其实就是调用ThreadLocal的get()
return sThreadLocal.get();
}
}
2.如果不知道ThreadLocal是什么意思,自己去查API,我没这么大气和你讲。
3.所以我们可以这样用:
public class MainActivity extends Activity {
private ProgressDialog mpDialog;
private int mCount = 0;
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
//update UI
System.out.println("----------update ui ok--------------"+Thread.currentThread().getId()); // Thread id 为1 说明在主线程中执行。
System.out.println("message arg1 : "+ msg.arg1); //因为这是主线程,所以可以在这时更新UI
super.handleMessage(msg);
}
};
private Thread downThread = new Thread(){
@Override
public void run() {
try{
while(mCount<=100){
mpDialog.setProgress(mCount++);
Thread.sleep(100); //模拟下载过程
}
// This is essentially the same as calling dismiss(),
//but it will also call your DialogInterface.OnCancelListener (if registered).
mpDialog.cancel();
System.out.println("------------download ok----------");
Message message = handler.obtainMessage();
message.arg1 = 10;
handler.sendMessage(message);
}catch(Exception ex){
mpDialog.cancel();
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button= (Button) this.findViewById(R.id.button);
imageView = (ImageView) this.findViewById(R.id.imageView01);
button.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View view) {
System.out.println("--------------download start----------------"+Thread.currentThread().getId()); //主线程的id为1
mCount = 0;
mpDialog = new ProgressDialog(MainActivity.this);
mpDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mpDialog.setTitle("dialogʾ");
mpDialog.setIcon(R.drawable.ic_launcher);
mpDialog.setMessage("好消息");
mpDialog.setMax(100);
mpDialog.setProgress(0);
mpDialog.setSecondaryProgress(50);
mpDialog.setIndeterminate(false);
mpDialog.setCancelable(true);
mpDialog.setButton("取消", new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
downThread.start();
mpDialog.show();
}
});
}
}
4.正如上面所说,一个新线程在默认情况下是没有Looper相关联的。所以需要自己创建。但android提供了一个HandlerThread,方便我们使用Looper。
public class HandlerThread extends Thread {
Looper mLooper;
/**
* Call back method that can be explicitly overridden if needed to execute some
* setup before Looper loops.
*/
protected void onLooperPrepared() {
}
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
/**
* This method returns the Looper associated with this thread. If this thread not been started
* or for any reason is isAlive() returns false, this method will return null. If this thread
* has been started, this method will block until the looper has been initialized.
* @return The looper.
*/
public Looper getLooper() {
if (!isAlive()) {
return null;
}
// If the thread has been started, wait until the looper has been created.
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
}
Looper分析。ThreadLocal有关的更多相关文章
- 分析 ThreadLocal 内存泄漏问题
ThreadLocal 的作用是提供线程内的局部变量,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或者组件之间一些公共变量的传递的复杂度.但是如果滥用 ThreadLocal,就可能会导 ...
- 分析ThreadLocal的弱引用与内存泄漏问题
目录 一.介绍 二.问题提出 2.1内存原理图 2.2几个问题 三.回答问题 3.1为什么会出现内存泄漏 3.2若Entry使用弱引用 3.3弱引用配合自动回收 四.总结 一.介绍 之前使用Threa ...
- Netty源码分析-- ThreadLocal分析(九)
为了更好地探讨Netty的内存模型,后面会用到,这里我还是决定跟大家一起看下ThreadLocal和FastThreadLocal的源码,有的时候我们在看源码的时候会一层层的遇到很多之前没有看过的内容 ...
- ThreadLocal 工作原理、部分源码分析
1.大概去哪里看 ThreadLocal 其根本实现方法,是在Thread里面,有一个ThreadLocal.ThreadLocalMap属性 ThreadLocal.ThreadLocalMap t ...
- Java 中 ThreadLocal 内存泄露的实例分析
前言 之前写了一篇深入分析 ThreadLocal 内存泄漏问题是从理论上分析ThreadLocal的内存泄漏问题,这一篇文章我们来分析一下实际的内存泄漏案例.分析问题的过程比结果更重要,理论结合实际 ...
- ThreadLocal的原理,源码深度分析及使用
文章简介 ThreadLocal应该都比较熟悉,这篇文章会基于ThreadLocal的应用以及实现原理做一个全面的分析 内容导航 什么是ThreadLocal ThreadLocal的使用 分析Thr ...
- ThreadLocal的使用及原理分析
文章简介 ThreadLocal应该都比较熟悉,这篇文章会基于ThreadLocal的应用以及实现原理做一个全面的分析 内容导航 什么是ThreadLocal ThreadLocal的使用 分析Thr ...
- ThreadLocal和ThreadLocalMap源码分析
目录 ThreadLocal和ThreadLocalMap源码分析 背景分析 定义 例子 源码分析 ThreadLocalMap源码分析 ThreadLocal源码分析 执行流程总结 源码分析总结 T ...
- 多线程之美2一ThreadLocal源代码分析
目录结构 1.应用场景及作用 2.结构关系 2.1.三者关系类图 2.2.ThreadLocalMap结构图 2.3. 内存引用关系 2.4.存在内存泄漏原因 3.源码分析 3.1.重要代码片段 3. ...
随机推荐
- BugHD 与你的应用一起成长
BugHD 新增功能 1.新增安装量.启动量的统计功能 BugHD SDK 1.3.0新增安装量.启动量的统计功能,在崩溃分析页面右上角可看到安装量和启动量. BugHD 体验优化 1.Android ...
- Java调用MQ队列
IBM MQ 6.0中设置两个队列,(远程队列.通道之类都不设置). 队列管理器是XIR_QM_1502 队列名称是ESBREQ IP地址是10.23.117.134(远程的一台电脑,跟我的电脑不在一 ...
- es 批量导入文件
首先是json格式的文件: curl -XPOST 'localhost:9200/bank/account/_bulk?pretty' --data-binary @accounts.json 1 ...
- Pycharm按装
1.python 官方 2.下载完成后点击exe 安装 3.按装完成后在cmd中输入 python 1.如果显示python版本 那么就安装成功 2.如果出现"python"不是外 ...
- 如何在taro的map循环中使用if条件渲染
在taro的jsx中,鉴于编译的机制,官方明确的表示了不能在map循环中使用if循环, 但是呢,官方也给出了解决办法,那就是提取变量或者是用三目运算嵌套的方法: 链接奉上:https://github ...
- 音频中PCM的概念
本文取自由http://blog.csdn.net/droidphone一部分 1. PCM是什么 PCM是英文Pulse-code modulation的缩写,中文译名是脉冲编码调制.我们知道在现实 ...
- 【.netcore学习】.netcore添加到 supervisor 守护进程自启动报错
配置 supervisor [program:HelloWebApp] command=dotnet run directory=/home/python/dotnet/myweb/mywebapi ...
- Delphi应用程序的调试(二)使用断点
Delphi应用程序的调试(二)使用断点 使用断点(Using Breakpoints) 当用户从Delphi IDE 运行程序时,程序全速运行,只会在设置了断点的地方停住. New Term 断点( ...
- 分布式实时日志系统(二) 环境搭建之 flume 集群搭建/flume ng资料
最近公司业务数据量越来越大,以前的基于消息队列的日志系统越来越难以满足目前的业务量,表现为消息积压,日志延迟,日志存储日期过短,所以,我们开始着手要重新设计这块,业界已经有了比较成熟的流程,即基于流式 ...
- How to install Wine on Ubuntu Linux 64bit
参考地址:https://linuxconfig.org/how-to-install-wine-on-ubuntu-linux-64bit The following linux command p ...