重新认识Android中的线程

这篇具有很好参考价值的文章主要介绍了重新认识Android中的线程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

线程的几种创建方式

  • new Thread:可复写Thread#run方法。也可以传递Runnable对象,更加灵活。
  • 缺点:缺乏统一管理,可能无限制新建线程,相互之间竞争,及可能占用过多系统的资源导致死机或oom。
 new Thread(new Runnable() {
            @Override
            public void run() {
                
            }
        }).start();
        
        class MyThread extends Thread{
            @Override
            public void run() {
                super.run();
            }
        }
        new MyThread().start();
  • AsyncTask,轻量级的异步任务工具类,提供任务执行的进度回调给UI线程
  • 场景:需要知晓任务执行的进度,多个任务串行执行
  • 缺点:生命周期和宿主的生命周期不同步,有可能发生内存泄漏(解决方案:将AsyncTask定义为静态内部类)
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;

public class ConcurrentTest {
    public static void test(Context context){
        class MyAsyncTask extends AsyncTask<String,Integer,String> {

            @Override
            protected String doInBackground(String... strings) {
                for (int i=0;i<10;i++){
                    publishProgress(i*10);
                }
                return strings[0];
            }

            @Override
            protected void onPostExecute(String s) {
                super.onPostExecute(s);
                Log.e("hzulwy","onPostExecute: "+s);//输出:execute myAsyncTask
            }

            @Override
            protected void onProgressUpdate(Integer... values) {
                super.onProgressUpdate(values);
                Log.e("hzulwy","onProgressUpdate: "+values[0]);//输出:10-90
            }
        }

        //适用于需要知道任务执行进度并更新UI的场景
        MyAsyncTask myAsyncTask = new MyAsyncTask();
        //默认串行
        myAsyncTask.execute("execute myAsyncTask");
        //并发执行
        myAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"execute myAsyncTask");

        //以这种方式提交的任务,所有任务串行执行,即先来后到,但是如果其中有一条任务休眠了,或者执行时间过长,后面的任务将被阻塞
        AsyncTask.execute(new Runnable() {
            @Override
            public void run() {
                Log.e("hzulwy","run:AsyncTask.execute");
            }
        });

        //适用于并发任务执行
        AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
            @Override
            public void run() {
                Log.e("hzulwy","run: THREAD_POOL_EXECUTOR AsyncTask.execute");
            }
        });
    }
}
  • HandlerThread:适用于主线程需要和工作线程通信,适用于持续性任务,比如轮询的场景,所有任务串行执行。
  • 缺点:不会像普通线程一样主动销毁资源,会一直运行着,所以可能会造成内存泄漏 ,需要程序员手动释放
public class ConcurrentTest {
    private static final int MSG_WHAT_1 = 1;

    public static void test1(){
        HandlerThread handlerThread = new HandlerThread("handler-thread");
        handlerThread.start();
        handlerThread.quitSafely();//在适当的地方释放资源
        
        MyHandler myHandler = new MyHandler(handlerThread.getLooper());
        myHandler.sendEmptyMessage(MSG_WHAT_1);
    }

    static class MyHandler extends Handler{
        public MyHandler(Looper looper){
            super(looper);
        }
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            Log.e("hzulwy","handleMessage: "+msg.what);//输出:1
            Log.e("hzulwy","handleMessage: "+Thread.currentThread().getName());//输出:handler-thread
        }
    }
}
  • IntentService:适用于我们的任务需要跨页面读取任务执行的进度,结果。比如后台上传图片,批量操作数据库等。任务执行完成后,就会自我结束,所以不需要手动stopservice,这是它与service的区分。IntentService包含了service的全部特色。
    class MyIntentService extends IntentService{

        @Override
        protected void onHandleIntent(@Nullable Intent intent) {
            int command = intent.getIntExtra("command",0);
            //...
            
        }
        context.startService(new Intent());
    }
  • ThreadPoolExecutor:适用于快速处理大量耗时较短的任务场景(使用最广泛)
        Executors.newCachedThreadPool();//线程可复用线程池
        Executors.newFixedThreadPool(1);//固定线程数量的线程池
        Executors.newScheduledThreadPool(1);//指定定时任务的线程池
        Executors.newSingleThreadExecutor();//线程数量为1的线程池

线程的优先级

        Thread thread = new Thread();
        thread.start();
        
        int ui_proi = Process.getThreadPriority(0);
        int th_proi = thread.getPriority();
        
        //输出结果
        ui_proi =5;
        th_proi = 5;
  • 线程的优先级具有继承性,在某线程中创建的线程会继承此线程的优先级。那么我们在UI线程中创建了线程,则线程优先级是和UI线程优先级一样,平等的和UI线程抢占CPU时间片资源。
  • JDK api,限制了新设置的线程的优先级必须为[1~10],优先级priority的值越高,获取cpu时间片的概率越高。UI线程的优先级为5。使用这种方式来设置优先级对线程影响的概率并不大。
  • Android api,可以为线程设置更加精细的优先级(-20~19),优先级的值越低,获取CPU时间片的概率越高。UI线程优先级为-10。推荐使用,影响较大,而且与JDK的方式设置线程优先级互不影响。

Process.setThreadPriority(-10);

线程的几种状态与常用方法

重新认识Android中的线程,android
重新认识Android中的线程,android
重新认识Android中的线程,android文章来源地址https://www.toymoban.com/news/detail-676046.html

//需要保证wait-notify方法的调用顺序,即先wait后notify,否则会有假死的情况
 private volatile boolean hasNotify = false;
    final Object object = new Object();
    public void test2(){

        Thread thread1 = new Thread(new Runnable1());
        Thread thread2 = new Thread(new Runnable2());

        thread1.start();
        thread2.start();
    }

    class Runnable1 implements Runnable{
        @Override
        public void run() {
            Log.e("hzulwy","run:thread1 start");
            synchronized (object){
                try {
                    if(!hasNotify){//规避假死情况
                        object.wait(1000);
                    }

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            Log.e("hzulwy","run:thread1 end");
        }
    }

    class Runnable2 implements Runnable{
        @Override
        public void run() {
            Log.e("hzulwy","run:thread2 start");
            synchronized (object){
                object.notify();
                hasNotify = true;
            }
            Log.e("hzulwy","run:thread2 end");
        }
    }

    public void test2(){
    //一个线程需要等待另一个线程执行完才能继续的场景
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                Log.e("hzulwy","run: 1"+System.currentTimeMillis());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Log.e("hzulwy","run: 2"+System.currentTimeMillis());
            }
        });
        thread.start();
        try {
            thread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //等thread执行完成后才会执行下面的日志
        Log.e("hzulwy","test: 3"+System.currentTimeMillis());
        
        //输出结果:
        //run: 1
        //run: 2
        //test: 3
    }

到了这里,关于重新认识Android中的线程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 一起Talk Android吧(第五百三十八回:RxJava中的线程切换)

    各位看官们大家好,上一回中咱们说的例子是\\\"RxJava中的多线程操作\\\",本章回中介绍的例子是\\\"R xJava中的线程切换 \\\"。闲话休提,言归正转,让我们一起Talk Android吧! 我们在上一章回中介绍了如何创建多线程,本章回将介绍如何进行线程切换。线程切换是指在主线程和子线程之

    2023年04月08日
    浏览(84)
  • Android逆向学习(一)vscode进行android逆向修改并重新打包

    其实我不知道这个文章能不能写下去,其实我已经开了很多坑但是都没填上,现在专利也发出去了,就开始填坑了,本坑的主要内容是关于android逆向,主要的教程来源来自52破解论坛的大佬课程,但是那是windows版,我喜欢用linux,所以这是一个有比较大改动的学习教程,不过

    2024年02月10日
    浏览(47)
  • 【Android 12】认识窗口

    该文章为窗口层级结构系列文章的总结,重新回看这方面内容的时候我自己也有了一些新的感悟,希望通过本次总结能让大家再次对窗口有一个全面的认识。 一般来说,屏幕上最起码包含三个窗口,StatusBar窗口、Activity窗口以及NavigationBar窗口: 我们想要了解窗口,可以按照

    2024年01月17日
    浏览(35)
  • android apk 加固后重新签名

    针对于加固平台在加固的过程中不能配置签名文件,加固后的apk需要进行重新签名才能安装,并发布到应用市场。 第一步,用AS对项目进行打包,生成签名的apk文件。 第二步,使用加固平台,对apk包进行加固,加固完成后,得到一个加固后的apk。 第三步,我们可以使用Andr

    2024年02月06日
    浏览(56)
  • Android修改aar并重新打包

    目录 一.修改 aar 需要用到的工具(就一个工具,使用方式非常简单,别担心) 二.修改 aar 代码层业务逻辑 三.修改 aar layout 布局文件 四.附上recyclerview aar修改工程源码 注:(下面工具,点击名称可进入下载链接,如果链接失效,请百度搜索下载) Bandizip ,一款非常好用的解

    2024年02月15日
    浏览(37)
  • 【Android】反编译APK及重新打包

    1.下载 APK 反编译工具 首先,需要下载一个 APK 反编译工具,例如 Apktool。可以在官网(https://apktool.org/docs/install)上下载最新版本的 Apktool,也可以使用包管理器来安装。 2.反编译 APK 文件 将要修改包名的 APK 文件放到一个新建的文件夹中,然后打开终端(命令行窗口),进入

    2024年04月11日
    浏览(44)
  • Android反编译修改apk并重新打包

            Apktool 是反编译Apk的第三方工具,它可以反编译资源,并在修改之后重新生成Apk          注意:apktool 依赖 Java1.8。请使用 java -version 查看,是否为1.8或更高版本。 1. 使用apktool.jar反编译解包 将需要编译的apk和apktool.jar放到同一个文件夹下 在cmd终端,cd到此目录下

    2023年04月13日
    浏览(51)
  • 【Android -- JNI 和 NDK】认识 NDK

    定义 :Native Development Kit ,是 Android 的一个工具开发包。 NDK 是属于 Android 的,与 Java 并无直接关系 作用 :快速开发 C、 C++ 的动态库,并自动将 so 和应用一起打包成 APK 即可通过 NDK 在 Android 中 使用 JNI 与本地代码(如C、C++)交互 应用场景 :在 Android 的场景下使用 JNI 。

    2024年02月11日
    浏览(43)
  • Android每次创建一个项目,就会重新下载.gradle文件

    每次重新创建一个项目时,需要下载所对应的.gradle文件,但是你的磁盘里有相应的.gradle文件,随着你创建的Project越多,下载的gradle文件就会越多,占用内存就会越大 。 首先设置 Gradle user home 的相对路径,(第一次设置时,加载Gradle文件会有点慢,如有报错或重新下载,直

    2024年02月12日
    浏览(64)
  • Android super.img的解包和重新组包

    Android10开始使用动态分区,system、vendor、 odm等都包含在super.img里面,可以按如下方式对super.img进行解包和组包。 super的解包需要工具lpunpack,但是默认没有编译,源码目录位于:system/extras/partition_tools/ ,需要手动编译生成; 在android根目录下执行 编译后生成 out/host/linux-86/b

    2024年02月16日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包