Android多线程基础

Android中多线程

  • 1.继承Thread类,重写run方法;
  • 2.实现Runnable接口,重写run方法;
  • 3.通过Callable和FutureTask创建线程
  • 4.通过线程池创建线程
  • 5 .AsyncTask
  • 6 .HandlerThread
  • 7.IntentService
    Activity.runOnUiThread(Runnable)
  • 8 AsyncQueryHandler

2)View.post(Runnable) ;View.postDelay(Runnable , long)

Android中多线程主要有Java和Android两种实现方式组成;Java中实现多线程的类在java.util.concurrent包下,主要有:继承Thread、实现Runnable接口、实现Callable< T >接口、

Java中多线程

(一) 、最简单实现多线程方式

继承Thread类和实现Runnable接口是Java入门级的新起线程的方法;最简单的匿名内部类实现方式;

   new Thread(() -> { }).start();

   Runnable runThread = () -> {};
   runThread.run();


   new Thread(new Runnable() {
        @Override
        public void run() {

        }
    }).start();

其中Thread类是实现Runnale的,并且Thread提供了诸多对线程的操作管理方法;
Runnable则是光杆司令interface一个,就连最基本的start都要借助其他类开始执行,谁让它是interface呢。可以startRunnable的有Thread的start方法、Executor实现类中execute方法、ExecutorService实现类中的submit方法;

(二)Callable< V >和Future< V >创建线程

先回顾一下Runnable和Callable< V >源码吧;

//Runnable 源码
@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

//Callable<V>源码
public interface Callable<V> {
    //返回V对象
    V call() throws Exception;
}

在源码中:
Runnable 接口中声明返回值为Void的run方法;所以Runnable开启的线程犹如脱缰骏马任其驰骋难以掌控,结果导致两个问题:
1.无法直接获取到线程执行执行的结果;2.不能直接捕获线程执行中的异常;
正是由于Runnable的“无法无天”难以控制,所以Java中的Callable< v >应用而生;
在Callable< v >源码可以看到与Runnable不同的是Callable< v >接口引入泛型V,在声明的call函数返回V 并且抛出Exception真是应对Runnable中的连个问题。

先看Future源码吧;

//Future<V>源码
public interface Future<V> {
   //取消这个线程 返回ture 取消成功;false 取消失败
    boolean cancel(boolean mayInterruptIfRunning);

    //判断该Future是否可以取消
    boolean isCancelled();

   //该Future是否完成
    boolean isDone();

    //获取该线程返回的结果,如果线程为执行完阻塞,等待执行完再返回
    V get() throws InterruptedException, ExecutionException;

    //获取该线程返回的结果,设置超时
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

Future只是定义规范接口,FutureTask是它一个实现类【有点类似List和ArrayList关系】,FutureTask同时实现RunnableFuture< V > 接口,RunnableFuture< V > 是实现了Runnable和Future< V > ; 因此FutureTask具备了Future的能力;

实现Callable< T >接口多线程例子

public static void main(String[] args) {
 try {
             //FutureTask启动线程
            CallableMThread mThread = new CallableMThread();
            FutureTask<String> task = new FutureTask<String>(mThread);
            task.run();
            //返回的String结果
            String resualt = task.get();
            System.out.println(resualt);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        //线程池submit开启多线程
try {
             CallableMThread mThread = new CallableMThread();
            ExecutorService threadPool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
            Future<String> submit = threadPool.submit(mThread);
            String resualt = submit.get();
            System.out.println(resualt);
            threadPool.shutdown();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

}
//内部类的实现Callable<V>开启新线程方式
 class CallableMThread implements Callable<String> {

        @Override
        public String call() throws Exception {
            // TO DO
            return "ThreadID :" + Thread.currentThread().getId() + " ThreadRandom :" + (Math.random() * 1000);
        }
    }

AsyncTask多线程

AsyncTask就没什么好多讲的了直接看例子吧

public class MainActivity extends Activity {
    @BindView(R.id.imageView)
    ImageView imageView;
    private String bUrl = "https://www.baidu.com/img/bd_logo1.png?qua=high&where=super";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        new AsyncThread().execute(bUrl);
    }

public Bitmap downloadUrlBitmap(String bitmapUrl) {
        Bitmap bitmap = null;
        //String strUrl = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1524503878682&di=98234ccb6ca81bfe209aef92e0888eed&imgtype=0&src=http%3A%2F%2Fimg5.pcpop.com%2FArticleImages%2F500x375%2F3%2F3542%2F003542587.jpg";
        HttpURLConnection mHttpURLConnection = null;
        try {
            URL url = new URL(bitmapUrl);
            mHttpURLConnection = (HttpURLConnection) url.openConnection();
            mHttpURLConnection.setConnectTimeout(3000);
            mHttpURLConnection.setRequestMethod("GET");
            inputStream = mHttpURLConnection.getInputStream();
            bufferedInputStream = new BufferedInputStream(inputStream, 4 * 1024);
            bitmap = BitmapFactory.decodeStream(bufferedInputStream);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (mHttpURLConnection != null) {
                mHttpURLConnection.disconnect();
            }
            CloseUtils.closeQuietly(inputStream);
            CloseUtils.closeQuietly(bufferedInputStream);
        }
        return bitmap;
    }

class AsyncThread extends AsyncTask<String,Integer ,Bitmap>{

        @Override
        protected Bitmap doInBackground(String... strings) {
            return downloadUrlBitmap(bUrl);
        }
        //主线程中 异步任务之前
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }
        //主线程中 异步任务之后返回结果【doInBackground返回的结果】
        @Override
        protected void onPostExecute(Bitmap bitmap) {
            super.onPostExecute(bitmap);
            imageView.setImageBitmap(bitmap);
        }
        //主线程中 【下载进度回调】
        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
        }
        //主线程中 【异步任务取消回调】
        @Override
        protected void onCancelled(Bitmap bitmap) {
            super.onCancelled(bitmap);
        }

        @Override
        protected void onCancelled() {
            super.onCancelled();
        }
    }
}

Java终止线程的方式
1.使用标志位,使线程正常退出,即run方法执行完正常退出;
2.使用stop方法终止线程,但是stop、suspend和resume都已经被Java列入过期方法中,可能产生不确定后果;
3.interrupt中断线程(与return结合使用);
4.抛出异常;
Java线程优先级
java线程的优先级继承性:Java线程优先级具有继承性,随机性

java 线程安全问题
1.变量安全;
方法内部是变量是安全,全局变量(没有关键字final修饰)是非安全

synchronized锁的释放:
synchronized不具有继承性
1.运行完成;
2.运行时抛出异常:

一、Handel消息传递机制

1.主线程Handler消息传递机制

Android 中Handler在作用和功能就不用多说了,个人浅薄认识Handler根本上也是通过共享数据实现线程通信的
Handler采用了类似[观察者模式]设计思想,主线程中通过继承Handler成为观察者子线程中借助Handler对象发布消息Looper负责检测目标MessageQueue中的变化,如果目标Queue的size发生变化,立即通知观察者主线程并且把message传递给观察者主线程的调度者,从而实现线程之间通信;
整个过程其实就借助共享变量Message实现消息传递的,而Looper是负责检测和传递,MessageQueue实现缓存策略。

2.子线程中的Handler传递消息

在开发中很场景是需要在子线程中处理繁杂的逻辑,这个时候在子线程结合Handler就很好解决问题了,在Android主线程中默认为Handler时需要开启Looper,不停去MessageQueue读取Message,实现Message的及时处理;所以在子线程就需要手动实现Looper;例如在run方法中通过 Looper.prepare()和Looper.loop()即可实现。当然了这么ease的场景Google开发人员早就考虑到这一点了,所以HandlerThread就现身了;HandlerThread也是继承Thread,然后实现Looper,并且实现一些很简单的功能;HandlerThread源码总共才几十行而已一眼就看明白了;

子线程中的Handler的应用

public class MainActivity extends Activity {
    @BindView(R.id.action_a)
    Button actionA;
    @BindView(R.id.action_b)
    Button actionB;
    private TestThread testThread;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        initThread();
        initHandlerThread()
    }

    //创建子线程实现Handel
   private void initThread(){
        //创建子线程
        testThread = new TestThread();
        testThread.start();
    }

    //创建HandlerThread
    private void initHandlerThread(){
        HandlerThread handlerThread = new HandlerThread("HandlerThread",Thread.NORM_PRIORITY);
        handlerThread.start();
        mThreadHandler = new Handler(handlerThread.getLooper()) {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                //TODO OTHRER
                }
            }
        };
    }


    @OnClick({R.id.action_a, R.id.action_b})
    public void onViewClicked(View view) {
        switch (view.getId()) {
            case R.id.action_a:
                //向TestThread线程Handler发消息
                testThread.handler.sendEmptyMessage(0);
                break;
            case R.id.action_b:
               //向ThreadHandler线程Handler发消息
               mThreadHandler.sendEmptyMessage(1);
                break;
        }
    }

//子线程
class TestThread extends Thread {
        public Handler handler;

        @SuppressLint("HandlerLeak")
        @Override
        public void run() {
            Looper.prepare();
            handler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                   //TODO OTHRER
                }
            };
            Looper.loop();
        }
    }
}

猜你喜欢

转载自blog.csdn.net/black_bird_cn/article/details/80905554