Skip to content

2019-08-16:请说一下你在项目中是如何使用子线程的?子线程和service有什么区别,应用场景有什么不同? #14

Open

Description

@liyilin-jack
No description provided.

Activity

  1. MicroKibaco commented on Aug 16, 2019

    @MicroKibaco
    Owner

    一. Android开启子线程方式

    1. Thread

    public class ThreadDemo implements TestDemo {
        @Override
        public void runTest() {
    
            Thread thread = new Thread() {
                @Override
                public void run() {
                    System.out.println("Thread started!");
                }
            };
            thread.start();
    
        }
    }

    2. Runnable

     /**
      * 使用 Runnable 类来定义工作
      */
     public class RunnableDemo implements TestDemo {
         @Override
         public void runTest() {
             Runnable runnable = new Runnable() {
                 @Override
                 public void run() {
                     System.out.println("Thread with Runnable started!");
                 }
             };
     
             Thread thread = new Thread(runnable);
             thread.start();
         }
     }  

    3. ThreadFactory

     public class ThreadFactoryDemo implements TestDemo {
          @Override
          public void runTest() {
              ThreadFactory factory = new ThreadFactory() {
                  @Override
                  public Thread newThread(Runnable r) {
                      AtomicInteger count = new AtomicInteger(0);
                      return new Thread(r, "Thread-" + count.incrementAndGet());
                  }
              };
      
      
              Runnable r = new Runnable() {
                  @Override
                  public void run() {
                      System.out.println(Thread.currentThread().getName() + " started!");
                  }
              };
      
              final Thread thread = factory.newThread(r);
              thread.start();
              final Thread thread1 = factory.newThread(r);
              thread1.start();
          }
      } 
     

    4. Executor 和线程池

    public class ExecutorDemo implements TestDemo {
        @Override
        public void runTest() {
            Runnable runnable =   new Runnable() {
                @Override
                public void run() {
                    System.out.println("Thread with Runnable started!");
                }
            };
    
            final ExecutorService executor = Executors.newCachedThreadPool();
            executor.execute(runnable);
            executor.execute(runnable);
            executor.execute(runnable);
        }
    }

    5. Callable 和 Future

    public class CallableDemo implements TestDemo {
        @Override
        public void runTest() {
            final Callable<String> callable = new Callable<String>() {
                @Override
                public String call() throws Exception {
    
                    try {
                        Thread.sleep(1500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    return "Done!";
                }
            };
    
            final ExecutorService executor = Executors.newCachedThreadPool();
            final Future<String> future = executor.submit(callable);
    
            try {
                final String result = future.get();
                System.out.println("result: " + result);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
     

    6. IntentService

    public static class MyIntentService extends IntentService{
            public MyIntentService(String name) {
                super(name);
            }
    
            @Override
            protected void onHandleIntent(Intent intent) {
                //这个方法执行在子线程,里面可以做耗时的操作
            }
        }
     

    7. HandlerThread

    HandlerThread mHandlerThread = new HandlerThread("MyHandlerThread");;
    mHandlerThread.start();//开启子线程
     Handler mhandler = new Handler(mHandlerThread.getLooper()){
         @Override
         public void handleMessage(Message msg) {
             //这个方法执行在子线程,里面可以做耗时的操作
         }
     };
    
     mhandler.sendEmptyMessage(10);

    8. AsyncTask

    new AsyncTask<String, Integer, Boolean>() {
        protected void onPreExecute() {
            super.onPreExecute();
        }
    
        protected Boolean doInBackground(String... params) {
            publishProgress(1);
            return null;
        }
    
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
    
        protected void onPostExecute(Boolean result) {
            super.onPostExecute(result);
        }
    
    }.execute("abc");
     

    二. 子线程和service有什么区别

    • service 用于检测后台活动空间,如:音乐播放器等
    • 子线程可以处理一些异步操作,需要注意死锁,同步,异步,阻塞,非租塞等问题

    三. 常见线程或线程池选择

    Executor , HandlerThead 和 IntentService 比较

    原则: 哪个简单用哪个

    • 能用Executor 就用 Executor
    • 需要用到「后台线程推送任务到 UI线程」 时,再考虑用Handler 或 AsyncTask
    • HandlerThread 的使用场景: 原本它设计的使用场景是「在已经运行的指定线程上执行代码」,但现实开发中,除了主线程几乎没有这种需求,因为 HandlerThread 和 Executor 相比实际应用中并没有实际优势,反而用起来会更麻烦点,不过这两者使用谁就用谁.
    • IntentService:首先,他是一个Service;另外,它在处理线程本身,没有比Executor 有任何优势
  2. liu1813565583 commented on Aug 16, 2019

    @liu1813565583
    Contributor

     Thread和Service的区别:

    1)

    Thread 是程序执行的最小单元,它是分配CPU的基本单位,可以用 Thread 来执行一些异步的操作。
    如果是Local Service,那么对应的 Service 是运行在主进程的 main 线程上的。如果是Remote Service,那么对应的 Service 则是运行在独立进程的main 线程上。因此 Service不是线程!
    2)

    Thread 的运行是独立于 Activity 的,也就是说当一个 Activity 被 finish 之后,如果你没有主动停止Thread 或者Thread 里的 run 方法没有执行完毕的话,Thread 也会一直执行。因此这里会出现一个问题:当 Activity 被 finish 之后,你不再持有该 Thread 的引用。另一方面,你没有办法在不同的 Activity 中对同一 Thread 进行控制。
    而任何 Activity 都可以控制同一 Service,而系统也只会创建一个对应 Service 的实例。因此你可以把 Service 想象成一种消息服务,而你可以在任何有 Context 的地方调用 Context.startService、Context.stopService、Context.bindService,Context.unbindService,来控制它,你也可以在 Service 里注册 BroadcastReceiver,在其他地方通过发送 broadcast 来控制它,当然这些都是 Thread 做不到的。
    3) Service组件主要有两个目的:后台运行和跨进程访问。service可以在android系统后台独立运行,线程是不可以。

    1. Service类是可以供其他应用程序来调用这个Service的而Thread只是在本类中在使用,如果本类关闭 那么这个thread也就下岗了而Service类则不会.
  3. gys0000 commented on Aug 16, 2019

    @gys0000

    Thread和Service是两码事,没什么关系。如果非要说出点关系,就是都经常被提到在后台工作。可这个后台是什么呢?他们两个的后台是一个东西吗?
    线程是可以脱离Activity执行的,一个Activity结束是没有停止线程,那么这个线程就会变成一个僵尸线程一直执行。之前没有经过验证,断章取义的得出线程可以在进程之外进行运行的结论,这真是学习的大忌。。。
    首先放上我感觉还好的两篇博文:
    深入剖析Android中Service和Thread区别
    安卓中线程和服务的区别?

    Thread

    Thread是程序执行的最小单元,在 Android里边一般界面事物都是运行在主线程的,耗时的操作都是放到子线程中操作。项目中一般使用线程池来操作线程,这样可以避免频繁的创建和销毁线程造成的时间和内存的浪费。线程在使用结束之后需要停止并且被销毁,如果在整个界面销毁或者整个进程被销毁时没有停止并销毁子线程,这个子线程就会一直运行下去,这就有可能造成MemoryLeak的问题。

    Service

    Service个人认为可以理解成没有界面的Activity,它是四大组件之一,也是运行在主线程的,所以不能在里边做耗时操作,service的耗时操作需要新建子线程,然后放到子线程中。

    服务不是什么事情都没有做,它做了一件非常重要的事情:提高了它所在进程的优先级

    Activity很难对Thread进行控制,当Activity被销毁之后,就没有任何其它的办法可以再重新获取到之前创建的子线程的实例。而且在一个Activity中创建的子线程,另一个Activity无法对其进行操作。但是Service就不同了,所有的Activity都可以与Service进行关联,然后可以很方便地操作其中的方法,即使Activity被销毁了,之后只要重新与Service建立关联,就又能够获取到原有的Service中Binder的实例。因此,使用Service来处理后台任务,Activity就可以放心地finish,完全不需要担心无法对后台任务进行控制的情况。

  4. liyilin-jack commented on Aug 18, 2019

    @liyilin-jack
    Author

    首先来说一说子线程吧

    在Android进程中,默认有一个“主线程”,为了保证UI更新的一致性,只能在主线程中执行UI更新的操作。如果在主线程中执行了过多的耗时任务,就会导致主线程卡顿的现象。所以我们才有了在“子线程”中执行耗时任务的这个概念。

    开启子线程的方式也很简单,一是继承Thread,实现run方法;二是直接创建一个线程。但是在Android中一般不建议直接使用Thread的方法,而是要把线程使用线程池来统一管理和复用,一般我们会使用ThreadPoolExecutor来管理线程的创建和耗时任务的处理。

    然后再说一个点,就是一般我们都认为子线程是不能更新UI的。

    我们首先要分析下,为什么Android设计不让我们在子线程中更新UI呢?一般情况下我们的更新UI是针对单个window的绘制,所以在单个线程---主线程中更新UI可以避免window的数据与其他线程共享,从而避免UI更新的线程同步问题。Android在framework层也会做出判断,如果当前更新UI的线程不是主线程,就直接抛出异常。

    那子线程可以更新UI吗?Android中提供了两个类,一个是TextureView,这个view与当前window使用的一个window元素,当这个类在子线程中更新UI时,会对当前window进行绘制的canvas进行加锁,保证UI绘制的一致性。另一个时SurfaceView,这个view是完全使用了另一个window,直接避免了window和canvas的共享问题,所以当然也是没有一致性问题需要处理的。

    再来说下service,serivce是Android设计用来执行和UI无关的业务逻辑的,但是需要注意的是,service仍然是跑在主线程中的,所以依然需要在执行耗时任务时开启子线程来执行。这一点可以参考上文中子线程的使用方式。

    那service的意义是什么呢?
    我理解,是为了便于对与UI无关的逻辑代码进行封装和管理,也是为了便于对线程声明周期进行管理,当service声明周期结束时,可以对 相关资源进行释放和关闭。

    那就这个题目的问题来看,service和thread有什么区别呢?这个问题本身就有问题,他们根本没有可比较性,完全是不同的东西。

    以上,END。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions