zoukankan      html  css  js  c++  java
  • ThreadLocal, HandlerThread, IntentService

    1. ThreadLocal用法详解和原理
    https://www.cnblogs.com/coshaho/p/5127135.html

    // ThreadLocal methods:
    public T get() {}
    public void set(T value) {}
    public void remove() {}
    protected T initialValue()
    
    ThreadLocal.get()
    ThreadLocal.set(T value)
    ThreadLocal.remove()
    ThreadLocal.initialValue()
    package com.coshaho.reflect;
    
    /**
     * ThreadLocal用法
     * @author coshaho
     *
     */
    public class MyThreadLocal {
        private static final ThreadLocal<Object> threadLocal = new ThreadLocal<Object>() {
            /**
             * ThreadLocal没有被当前线程赋值时或当前线程刚调用remove方法后调用get方法,返回此方法值
             */
            @Override
            protected Object initialValue() {
                System.out.println("调用get方法时,当前线程共享变量没有设置,调用initialValue获取默认值!");
                return null;
            }
        };
    
        public static void main(String[] args) {
            new Thread(new MyIntegerTask("IntegerTask1")).start();
            new Thread(new MyStringTask("StringTask1")).start();
            new Thread(new MyIntegerTask("IntegerTask2")).start();
            new Thread(new MyStringTask("StringTask2")).start();
        }
    
        public static class MyIntegerTask implements Runnable {
            private String name;
    
            MyIntegerTask(String name) {
                this.name = name;
            }
    
            @Override
            public void run() {
                for(int i = 0; i < 5; i++) {
                    // ThreadLocal.get方法获取线程变量
                    if (null == MyThreadLocal.threadLocal.get()) {
                        // ThreadLocal.et方法设置线程变量
                        MyThreadLocal.threadLocal.set(0);
                        System.out.println("线程" + name + ": 0");
                    } else {
                        int num = (Integer)MyThreadLocal.threadLocal.get();
                        MyThreadLocal.threadLocal.set(num + 1);
                        System.out.println("线程" + name + ": " + MyThreadLocal.threadLocal.get());
                        if(i == 3) {
                            MyThreadLocal.threadLocal.remove();
                        }
                    }
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
    
        }
    
        public static class MyStringTask implements Runnable {
            private String name;
    
            MyStringTask(String name) {
                this.name = name;
            }
    
            @Override
            public void run() {
                for(int i = 0; i < 5; i++) {
                    if(null == MyThreadLocal.threadLocal.get()) {
                        MyThreadLocal.threadLocal.set("a");
                        System.out.println("线程" + name + ": a");
                    } else
                        String str = (String)MyThreadLocal.threadLocal.get();
                        MyThreadLocal.threadLocal.set(str + "a");
                        System.out.println("线程" + name + ": " + MyThreadLocal.threadLocal.get());
                    } try {
                        Thread.sleep(800);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
    
        }
    }

    2. HandlerThread用法详解和原理

    HandlerThread的特点

    • HandlerThread将loop转到子线程中处理,说白了就是将分担MainLooper的工作量,降低了主线程的压力,使主界面更流畅。

    • 开启一个线程起到多个线程的作用。处理任务是串行执行,按消息发送顺序进行处理。HandlerThread本质是一个线程,在线程内部,代码是串行处理的。

    • 但是由于每一个任务都将以队列的方式逐个被执行到,一旦队列中有某个任务执行时间过长,那么就会导致后续的任务都会被延迟处理。

    • HandlerThread拥有自己的消息队列,它不会干扰或阻塞UI线程。

    • 对于网络IO操作,HandlerThread并不适合,因为它只有一个线程,还得排队一个一个等着。

    HandlerThread

    HandlerThread本质上就是一个普通Thread,只不过内部建立了Looper.

    HandlerThread的常规用法

    • 创建一个HandlerThread

    mThread = new HandlerThread("handler_thread");

      • 启动一个HandlerThread

        mThread.start();

      • 退出循环
        Looper是通过调用loop方法驱动着消息循环的进行: 从MessageQueue中阻塞式地取出一个消息,然后让Handler处理该消息,周而复始,loop方法是个死循环方法。

     【Android Handler、Loop 的简单使用】 介绍了子线程和子线程之间的通信。

    package lib.com.myapplication;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Looper;
    import android.os.Message;
    import android.support.v7.app.AppCompatActivity;
     
    public class MainActivity extends AppCompatActivity {
     
        private Handler handler1 ;
        private Handler handler2 ;
     
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            new MyThread1().start();
            new MyThread2().start();
        }
     
        class MyThread1 extends Thread {
     
            @Override
            public void run() {
                super.run();
     
                Looper.prepare();
     
                handler1 = new Handler(){
                    @Override
                    public void handleMessage(Message msg) {
                        super.handleMessage(msg);
                        System.out.println( "threadName--" + Thread.currentThread().getName() + "messageWhat-"+ msg.what );
                    }
                };
     
                try {
                    sleep( 3000 );
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
     
                handler2.sendEmptyMessage( 2 ) ;
     
                Looper.loop();
            }
        }
     
        class MyThread2 extends Thread {
            @Override
            public void run() {
                super.run();
                Looper.prepare();
     
                handler2 = new Handler(){
                    @Override
                    public void handleMessage(Message msg) {
                        super.handleMessage(msg);
                        System.out.println( "threadName--" + Thread.currentThread().getName() + "messageWhat-"+ msg.what );
                    }
                };
     
                try {
                    sleep( 4000 );
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
     
                handler1.sendEmptyMessage( 5 ) ;
     
                Looper.loop();
            }
        }
    }

    很明显的一点就是,我们要在子线程中调用Looper.prepare() 为一个线程开启一个消息循环,默认情况下Android中新诞生的线程是没有开启消息循环的。(主线程除外,主线程系统会自动为其创建Looper对象,开启消息循环。) Looper对象通过MessageQueue来存放消息和事件。一个线程只能有一个Looper,对应一个MessageQueue。 然后通过Looper.loop() 让Looper开始工作,从消息队列里取消息,处理消息。

    注意:写在Looper.loop()之后的代码不会被执行,这个函数内部应该是一个循环,当调用mHandler.getLooper().quit()后,loop才会中止,其后的代码才能得以运行。

    然而这一切都可以用HandlerThread类来帮我们做这些逻辑操作。

    HandlerThreadDemo:

    package com.app;
    
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.HandlerThread;
    import android.os.Message;
    import android.support.v7.app.AppCompatActivity;
    import android.util.Log;
    
    public class MainActivity extends AppCompatActivity {
    
        private HandlerThread myHandlerThread;
        private Handler handler;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            //创建一个线程,线程名字:handler-thread
            myHandlerThread = new HandlerThread( "handler-thread");
            //开启一个线程
            myHandlerThread.start();
            //在这个线程中创建一个handler对象
            handler = new Handler( myHandlerThread.getLooper() ) {
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    //这个方法是运行在 handler-thread 线程中的 ,可以执行耗时操作
                    Log.d( "handler " , "消息: " + msg.what + "  线程: " + Thread.currentThread().getName()  );
    
                }
            };
    
            //在主线程给handler发送消息
            handler.sendEmptyMessage( 1 );
    
            new Thread(new Runnable() {
                @Override
                public void run() {
                 //在子线程给handler发送数据
                 handler.sendEmptyMessage( 2 );
                }
            }).start();
    
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
    
            //释放资源
            myHandlerThread.quit();
        }
    }

    3.IntentService用法详解和原理

    https://www.cnblogs.com/denluoyia/p/5997452.html


    IntentService是继承并处理异步请求的一个类,在IntentService内有一个工作线程来处理耗时操作,启动IntentService的方式和启动传统的Service一样,同时,当任务执行完后,IntentService会自动停止,而不需要我们手动去控制或stopSelf()。另外,可以启动IntentService多次,而每一个耗时操作会以工作队列的方式在IntentService的onHandleIntent回调方法中执行,并且,每次只会执行一个工作线程,执行完第一个再执行第二个,以此类推。

    HandlerThread thread = new HandlerThread()

    定义一个IntentService的子类:

    public class MIntentService extends IntentService {
    
        public MIntentService(){
            super("MIntentService");
        }
    
        /**
         * Creates an IntentService.  Invoked by your subclass's constructor.
         * @param name Used to name the worker thread, important only for debugging.
         */
        public MIntentService(String name) {
            super(name);
        }
    
        @Override
        public void onCreate() {
            Log.e("MIntentService--", "onCreate");
            super.onCreate();
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            Log.e("MIntentService--", "onStartCommand");
            return super.onStartCommand(intent, flags, startId);
        }
    
        @Override
        protected void onHandleIntent(Intent intent) {
            Log.e("MIntentService--", Thread.currentThread().getName() + "--" + intent.getStringExtra("info") );
            for(int i = 0; i < 100; i++){ //耗时操作
                Log.i("onHandleIntent--",  i + "--" + Thread.currentThread().getName());
            }
        }
    
        @Override
        public void onDestroy() {
            Log.e("MIntentService--", "onDestroy");
            super.onDestroy();
        }
    }

    开启IntentService服务:

     public void intentClick(View v){
            Intent intent = new Intent(this, MIntentService.class);
            intent.putExtra("info", "good good study");
            startService(intent);
     }

    Intent服务开启后,执行完onHandleIntent里面的任务就自动销毁结束,通过打印的线程名称可以发现是新开了一个线程来处理耗时操作的,即是耗时操作也可以被这个线程管理和执行,同时不会产生ANR的情况。

  • 相关阅读:
    Laravel笔记
    Mysql函数大全
    nginx中文文档
    解析富文本框
    VSCode的C++环境配置,多cpp在同一文件夹(json方式)
    UltraISO光盘刻录
    plog日志库(c++)
    .NET Core安装
    Halcon深度学习——奇异值检测
    C++命名规范
  • 原文地址:https://www.cnblogs.com/bluestorm/p/10563052.html
Copyright © 2011-2022 走看看