多线程(multithreading),是指从软件或者硬件上实现多个线程并发执行的技术。具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提升整体处理性能。具有这种能力的系统包括对称多处理机、多核心处理器以及芯片级多处理或同时多线程处理器。在一个程序中,这些独立运行的程序片段叫作“线程”(Thread),利用它编程的概念就叫作“多线程处理”。多线程的应用在开发中非常常见。
基础使用
Android多线程实现的基础使用包括:
- 继承Thread类
- 实现Runnable接口
- Handler
继承Thread类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class MyThread extends Thread{ @Override public void run(){ ... } } MyThread mt=new MyThread(“线程名称”); mt.start();
|
开发者会选择一种更加方便的方法去创建线程:匿名类
1 2 3 4 5 6 7
| new Thread("线程名称") { @Override public void run() { }.start();
|
实现Runnable接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| class MyThread implements Runnable{ .... @Override public void run(){ } } MyThread mt=new MyThread(); Thread td=new Thread(mt); td.start();
|
开发者会选择一种更加方便的方法去创建线程:匿名类
1 2 3 4 5 6 7 8 9 10 11 12 13
| Runnable mt = new Runnable() { @Override public void run() { } }; Thread mt1 = new Thread(mt, "窗口1"); mt1.start();
|
Java中真正能创建新线程的只有Thread类对象,通过实现Runnable的方式,最终还是通过Thread类对象来创建线程,所以对于实现了Runnable接口的类,称为线程辅助类;Thread类才是真正的线程类。
Handler
Handler的使用方式 因发送消息到消息队列的方式不同而不同,共分为2种:使用Handler.sendMessage()、使用Handler.post()
Handler.sendMessage()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| /** * 方式1:新建Handler子类(内部类) */ // 步骤1:自定义Handler子类(继承Handler类) & 复写handleMessage()方法 class mHandler extends Handler { // 通过复写handlerMessage() 从而确定更新UI的操作 @Override public void handleMessage(Message msg) { ...// 需执行的UI操作 } } // 步骤2:在主线程中创建Handler实例 private Handler mhandler = new mHandler(); // 步骤3:创建所需的消息对象 Message msg = Message.obtain(); // 实例化消息对象 msg.what = 1; // 消息标识 msg.obj = "AA"; // 消息内容存放 // 步骤4:在工作线程中 通过Handler发送消息到消息队列中 // 可通过sendMessage() / post() // 多线程可采用AsyncTask、继承Thread类、实现Runnable mHandler.sendMessage(msg); // 步骤5:开启工作线程(同时启动了Handler) // 多线程可采用AsyncTask、继承Thread类、实现Runnable /** * 方式2:匿名内部类 */ // 步骤1:在主线程中 通过匿名内部类 创建Handler类对象 private Handler mhandler = new Handler(){ // 通过复写handlerMessage()从而确定更新UI的操作 @Override public void handleMessage(Message msg) { ...// 需执行的UI操作 } }; // 步骤2:创建消息对象 Message msg = Message.obtain(); // 实例化消息对象 msg.what = 1; // 消息标识 msg.obj = "AA"; // 消息内容存放 // 步骤3:在工作线程中 通过Handler发送消息到消息队列中 // 多线程可采用AsyncTask、继承Thread类、实现Runnable mHandler.sendMessage(msg); // 步骤4:开启工作线程(同时启动了Handler) // 多线程可采用AsyncTask、继承Thread类、实现Runnable
|
警告提示:This Handler class should be static or leaks might occur (anonymous android.os.Handler)
官方解决方法:
1 2 3 4 5 6 7
| private Handler mHandler = new Handler(new Handler.Callback() {
@Override public boolean handleMessage(Message msg) { return false; } });
|
Handler.post()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| private Handler mhandler = new mHandler(); mHandler.post(new Runnable() { @Override public void run() { ... } });
|
复合使用
Android多线程实现的复合使用包括:
- AsyncTask
- HandlerThread
- IntentService
称为”复用“的主要原因是:这3种方式的本质原理都是Android多线程基础实现(继承Thread类、实现Runnable接口、Handler)的组合实现。下面,我将详细讲解。
AsyncTask
AsyncTask类属于抽象类,即使用时需实现子类
AsyncTask的使用步骤
- 创建 AsyncTask 子类 & 根据需求实现核心方法
- 创建 AsyncTask子类的实例对象(即 任务实例)
- 手动调用execute(()从而执行异步线程任务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
|
private class MyTask extends AsyncTask<Params, Progress, Result> { .... @Override protected void onPreExecute() { ... } @Override protected String doInBackground(String... params) { ... publishProgress(count); } @Override protected void onProgressUpdate(Integer... progresses) { ... } @Override protected void onPostExecute(String result) { ... } @Override protected void onCancelled() { ... } }
MyTask mTask = new MyTask();
mTask.execute();
|
HandlerThread
HandlerThread的本质:继承Thread类 & 封装Handler类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
|
HandlerThread mHandlerThread = new HandlerThread("handlerThread");
mHandlerThread.start();
Handler workHandler = new Handler( handlerThread.getLooper() ) { @Override public boolean handleMessage(Message msg) { ... return true; } });
Message msg = Message.obtain(); msg.what = 2; msg.obj = "B"; workHandler.sendMessage(msg);
mHandlerThread.quit();
|
IntentService
Android里的一个封装类,继承四大组件之一的Service
作用:处理异步请求 & 实现多线程
使用场景:线程任务需按顺序、在后台执行
- 最常见的场景:离线下载
- 不符合多个数据同时请求的场景:所有的任务都在同一个Thread looper里执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
| 步骤1:定义 IntentService的子类:传入线程名称、复写onHandleIntent()方法 public class myIntentService extends IntentService {
public myIntentService() { super("myIntentService"); }
@Override protected void onHandleIntent(Intent intent) { String taskName = intent.getExtras().getString("taskName"); switch (taskName) { case "task1": Log.i("myIntentService", "do task1"); break; case "task2": Log.i("myIntentService", "do task2"); break; default: break; } } @Override public void onCreate() { Log.i("myIntentService", "onCreate"); super.onCreate(); }
@Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i("myIntentService", "onStartCommand"); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { Log.i("myIntentService", "onDestroy"); super.onDestroy(); } }
步骤2:在Manifest.xml中注册服务 <service android:name=".myIntentService"> <intent-filter > <action android:name="cn.scu.finch"/> </intent-filter> </service> 步骤3:在Activity中开启Service服务 public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Intent i = new Intent("cn.scu.finch"); Bundle bundle = new Bundle(); bundle.putString("taskName", "task1"); i.putExtras(bundle); startService(i); Intent i2 = new Intent("cn.scu.finch"); Bundle bundle2 = new Bundle(); bundle2.putString("taskName", "task2"); i2.putExtras(bundle2); startService(i2); startService(i); } }
|
高级使用
线程池(ThreadPool)
1、ThreadPoolExecutor 创建基本线程池
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3,5,1,TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(100));
mThreadPoolExecute.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) {
for(int i = 0;i<30;i++){ final int finali = i; Runnable runnable = new Runnable() { @Override public void run() { try { Thread.sleep(2000); Log.d("Thread", "run: "+finali); Log.d("当前线程:",Thread.currentThread().getName()); } catch (InterruptedException e) { e.printStackTrace(); } } }; threadPoolExecutor.execute(runnable); } } });
|
其他几种常见的线程池
2.FixedThreadPool (可重用固定线程数)
3.CachedThreadPool (按需创建)
4.SingleThreadPool(单个核线的fixed)
5.ScheduledThreadPool(定时延时执行)
[1] https://blog.csdn.net/u013773608/article/details/124329942
[2] https://blog.csdn.net/qq_41648631/article/details/102871630