美文网首页
Android 多线程

Android 多线程

作者: 一只笔 | 来源:发表于2018-08-05 23:19 被阅读0次

Android 多线程实际上就是java SE 中的多线程,为了方便使用,封闭了一些类,如:AsyncTask,HandlerThread等。

多线程的实现---Thread和Runnable

   //Thread 实现
        new Thread() {
            @Override
            public void run() {
                super.run();
                //耗时操作
            }
        };
        //Runnable 实现
        new Thread(new Runnable() {
            @Override
            public void run() {
                //耗时操作
            }
        }).start();

其实Thread也是一个Runnable 因为它实现的Runnable接口

Thread 中的wait, sleep, join, yield

wait():进入等待池中同时失去同步锁,使用notify, notifyAll或指定睡眠时间唤醒。注意wiat, notify, notifyAll 都必须在synchronized block 中否则会抛异常。

seep():是Thread 的步态方法,使用线程休眠,因为是线程的步态方法,所以同步锁不会释放。

join():待目标线程执行完后再继续执行。

yield():让出执行权让其他线程执行。

wait()与sleep() 使用
线程启动后调用wait() 进行入等待状态,3秒后唤醒。

 public void test2() {
        Log.i(TAG, "主线程运行");
        Thread thread = new WaitThread();
        thread.start();
        long startTime = System.currentTimeMillis();
        try {
            synchronized (mLock) {
                Log.i(TAG, "主线程等待");
                mLock.wait();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Long endTime = System.currentTimeMillis();
        
        Log.i(TAG, "等待时间 :" + (endTime - startTime));
    }
    
    //等待线程
    class WaitThread extends Thread {
        @Override
        public void run() {
            try {
                synchronized (mLock) {
                    //休眠3秒后唤醒
                    Thread.sleep(3000L);
                    mLock.notifyAll();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            super.run();
        }
    }

运行结果 :


image.png

wait()与sleep() 使用

线程池

如果频繁创建线程new Thread(),不是个好办法,因为新建与销毁性能差,缺乏统一管理,占用过多系统资源容易导致死锁。
多线程优点:

  1. 重用存在的线程,减少开销。
  2. 有效控制最大并发线程数,提高系统资源的使用,避免堵塞。
  3. 提供定时执行,定期执行,单线程,并发数控制等功能 。

线程池都实现了ExecutorService接口,Android中最常见的四类具有不同特性的线程池分别为FixedThreadPool、CachedThreadPool、SingleThreadPool、ScheduleThreadExecutor.

  1. FixedThreadPool 创建指定的线程数量
    只有核心线程,并且数量固定的,也不会被回收,所有线程都活动时,因为队列没有限制大小,新任务会等待执行.
    优点:更快的响应外界请求.

  2. SingleThreadPool
    只有一个核心线程,确保所有的任务都在同一线程中按顺序完成.因此不需要处理线程同步的问题.

  3. CachedThreadPool 没有空线程时创建线程
    只有非核心线程,最大线程数非常大,所有线程都活动时,会为新任务创建新线程,否则会利用空闲线程(60s空闲时间,过了就会被回收,所以线程池中有0个线程的可能)处理任务.
    优点:任何任务都会被立即执行(任务队列SynchronousQueue相当于一个空集合);比较适合执行大量的耗时较少的任务.

  4. ScheduledThreadPool
    核心线程数固定,非核心线程(闲着没活干会被立即回收)数没有限制.
    优点:执行定时任务以及有固定周期的重复任务

FixedThreadPool 使用(指定创建固定的线程)

 //固定线程宾的使用
    public void fixedThreadPool(int size) throws ExecutionException, InterruptedException {
        //创建固定数量的线程池
                ExecutorService executorService = Executors.newFixedThreadPool(size);
        for (int i = 0; i < MAX; i++) {
            //提交任务
            Future<Integer> task = executorService.submit(new Callable<Integer>() {
                @Override
                public Integer call() throws Exception {
                    Log.i(TAG, "当前线程:" + Thread.currentThread().getName());
                    return fibc(40);
                }
            });
            //获取结果
            Log.i(TAG, "第:" + i + " 计算结果: " + task.get());
            
        }
    }
    
    //效率低下的斐波那契数,耗时操作
    public int fibc(int num) {
        if (num == 0) {
            return 0;
        }
        if (num == 1) {
            return 1;
        }
        return fibc(num - 1) +fibc(num - 2);
    }

      //调用,指定为3个线程
       fixedThreadPool(3);
   

运行结果:


image.png

可以看出线程创建是3个,并且都是按顺序执行的

CachedThreadPool 使用

 //cachedThreadPool使用
    private void cachedThreadPool() {
        //创建CachedThreadPool线程池
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i < MAX; i++) {
            //提交任务
            Future task = executorService.submit(new Runnable() {
                @Override
                public void run() {
                    //获取结果
                    Log.i(TAG, "当前线程:" + Thread.currentThread().getName() + " 计算结果: " + fibc(20));
                }
            });
        }
    }

 //调用
  cachedThreadPool();

计算结果:

image.png
没有空线程时创建线程

ScheduledExecutorService 使用(定时任务线程池)

private void scheduledThreadPool() {
       //创建定时线程池
       ScheduledExecutorService executorService = Executors.newScheduledThreadPool(3);
       //参数1延迟时间,参数2周期,参数3时间单位
       executorService.scheduleAtFixedRate(new Runnable() {
           @Override
           public void run() {
               //获取结果
               Log.i(TAG, "当前线程:" + Thread.currentThread().getName() + " 计算结果: " + fibc(20));
           }
       }, 1, 2, TimeUnit.SECONDS);
       
       executorService.scheduleAtFixedRate(new Runnable() {
           @Override
           public void run() {
               //获取结果
               Log.i(TAG, "22当前线程:" + Thread.currentThread().getName() + " 计算结果: " + fibc(30));
           }
       }, 1, 2, TimeUnit.SECONDS);
   }

//调用
scheduledThreadPool();

运行结果:


image.png

相关文章

网友评论

      本文标题:Android 多线程

      本文链接:https://www.haomeiwen.com/subject/nczbvftx.html