Android 多线程详解

Android 多线程详解Android 多线程详解一 多线程介绍在学习多线程之前我们首先要了解几个与多线程有关的概念 进程 进程指正在运行的程序 确切的来说 当一个程序进入内存运行 即变成一个进程 进程是处于运行过程中的程序 并且具有一定独立功能 线程 线程是进程中的一个执行单元 负责当前进程中程序的执行 一个进程中至少有一个线程 一个进程中是可以有多个线程的 这个应用程序也可以称之为多线程程序

Android 多线程详解
一.多线程介绍
在学习多线程之前我们首先要了解几个与多线程有关的概念。
进程:进程指正在运行的程序。确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于运行过程中的程序,并且具有一定独立功能。
线程:线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至
少有一个线程。一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序。
简而言之:一个程序运行后至少有一个进程,一个进程中可以包含多个线程。
什么是多线程呢?即就是一个程序中有多个线程在同时执行。
单线程程序:若有多个任务只能依次执行。
多线程程序:若有多个任务可以同时执行。
二.获取线程名称
static Thread [currentThread()] 返回对当前正在执行线程对象的引用
String [getName()] 返回该线程的名称
Thread.currentThread() 获取当前线程对象
Thread.currentThread().getName(); 获取当前线程对象的名称
主线程的名称:main;自定义的线程:Thread-0,线程多个时,数字顺延。如Thread-1……
进行多线程编程时,不要忘记了Java程序运行是从主线程开始,main方法就是主线程的线程执行内容。


public class MainActivity extends AppCompatActivity { @Override  protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //实例化对象  MyThread myThread=new MyThread("陈箫阳"); //开启子线程,调用Start方法切记不要调用Run方法  myThread.start(); for(int x=0; x<50; x++){ System.out.println("main"+x); } //获取子线程名字  System.out.println(myThread.getName()); //获取主线程名字  System.out.println(Thread.currentThread().getName()); } }
三.创建线程
创建线程的方式有三种:
1.继承Thread类
2.实现Runnable接口
3.实现Callable接口
Thread类
构造方法摘要:
Thread()分配新的Thread对象
Thread(String name)分配新的Thread对象,将指定的name作为其线程名称
常用方法
voidstart() 使该线程开始执行,Java虚拟机调用该线程的run方法
void  run()  该线程要执行的操作,如循环输出打印变量的值
static void  sleep(毫秒数)   在指定的毫秒数内让当前正在执行的线程休眠,暂停执行
创建新执行线程有两种方法。
1.一种方法是将类声明为 Thread 的子类。该子类应重写 Thread 类的 run 方法。创建对象,开启线程。run方法相当于其他线程的main方法。
2.另一种方法是声明一个实现 Runnable 接口的类。该类然后实现 run 方法。然后创建Runnable的子类对象,传入到某个线程的构造方法中,开启线程。
创建线程的步骤:
1 定义一个类继承Thread。
2 重写run方法。
3 创建子类对象,就是创建线程对象。
4 调用start方法,开启线程并让线程执行,同时还会告诉jvm去调用run方法。
测试类

public class MainActivity extends AppCompatActivity { @Override  protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //实例化对象  MyThread myThread=new MyThread("陈箫阳"); //开启子线程,调用Start方法切记不要调用Run方法  myThread.start(); for(int x=0; x<50; x++){ System.out.println("main"+x); } //获取子线程名字  System.out.println(myThread.getName()); //获取主线程名字  System.out.println(Thread.currentThread().getName()); } }
自定义线程类

public class MyThread extends Thread{ public MyThread(String name){ super(name); } @Override  public void run() { for(int x=0; x<50; x++){ System.out.println("Thread"+x); Log.i("thread","==="+x); } } }
创建线程的目的是什么?
是为了建立程序单独的执行路径,让多部分代码实现同时执行。也就是说线程创建并执行需要给定线程要执行的任务。
对于之前所讲的主线程,它的任务定义在main函数中。自定义线程需要执行的任务都定义在run方法中。
Thread类run方法中的任务并不是我们所需要的,只有重写这个run方法。既然Thread类已经定义了线程任务的编写位置(run方法),那么只要在编写位置(run方法)中定义任务代码即可。所以进行了重写run方法动作。








Runnable接口
创建线程的另一种方法是声明实现 Runnable 接口的类。该类然后实现 run 方法。然后创建Runnable的子类对象,传入到某个线程的构造方法中,开启线程。



方法摘要
void [run()] 使用实现接口Runnable的对象创建一个线程时,启动该线程将导致在独立执行的线程中调用对象的run
创建线程的步骤。
1、定义类实现Runnable接口
2、覆盖接口中的run方法
3、创建Thread类的对象
4、将Runnable接口的子类对象作为参数传递给Thread类的构造函数
5、调用Thread类的start方法开启线程










测试类

public class MainActivity extends AppCompatActivity { @Override  protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //创建线程执行目标类对象  Runnable runnable = new MyRunnable(); //将Runnable接口的子类对象作为参数传递给Thread类的构造函数  Thread thread = new Thread(runnable); Thread thread2 = new Thread(runnable); //开启线程  thread.start(); thread2.start(); for (int i = 0; i < 10; i++) { System.out.println("main线程:正在执行!" + i); } } }
自定义线程执行任务类

public class MyThread implements Runnable { //定义线程要执行的run方法逻辑  @Override  public void run() { for (int i = 0; i < 10; i++) { System.out.println("我的线程:正在执行!" + i); } } }
实现Runnable的原理
实现Runnable接口,避免了继承Thread类的单继承局限性。覆盖Runnable接口中的run方法,将线程任务代码定义到run方法中。
创建Thread类的对象,只有创建Thread类的对象才可以创建线程。线程任务已被封装到Runnable接口的run方法中,而这个run方法所属于Runnable接口的子类对象,所以将这个子类对象作为参数传递给Thread的构造函数,这样,线程对象创建时就可以明确要运行的线程的任务。




实现Runnable的好处
实现Runnable接口避免了单继承的局限性,所以较为常用。实现Runnable接口的方式,更加的符合面向对象,线程分为两部分,一部分线程对象,一部分线程任务。继承Thread类,线程对象和线程任务耦合在一起。一旦创建Thread类的子类对象,既是线程对象,有又有线程任务。实现runnable接口,将线程任务单独分离出来封装成对象,类型就是Runnable接口类型。Runnable接口对线程对象和线程任务进行解耦。


Callable接口
Callable接口:与Runnable接口功能相似,用来指定线程的任务。其中的call()方法,用来返回线程任务执行完毕后的结果,call方法可抛出异常。
在此处需要用到线程池
线程池概念
线程池,其实就是一个容纳多个线程的容器,其中的线程可以反复使用,省去了
频繁创建线程对象的操作,无需反复创建线程而消耗过多资源。
Android 多线程详解


为什么要使用线程池?
在java中,如果每个请求到达就创建一个新线程,开销是相当大的。在实际使用中,创建和销毁线程花费的时间和消耗的系统资源都相当大,甚至可能要比在处理实际的用户请求的时间和资源要多的多。除了创建和销毁线程的开销之外,活动的线程也需要消耗系统资源。如果在一个jvm里创建太多的线程,可能会使系统由于过度消耗内存或“切换过度”而导致系统资源不足。为了防止资源不足,需要采取一些办法来限制任何给定时刻处理的请求数目,尽可能减少创建和销毁线程的次数,特别是一些资源耗费比较大的线程的创建和销毁,尽量利用已有对象来进行服务。线程池主要用来解决线程生命周期开销问题和资源不足问题。通过对多个任务重复使用线程,线程创建的开销就被分摊到了多个任务上了,而且由于在请求到达时线程已经存在,所以消除了线程创建所带来的延迟。这样,就可以立即为请求服务,使用应用程序响应更快。另外,通过适当的调整线程中的线程数目可以防止出现资源不足的情况。




使用线程池方式–Runnable接口和Callable接口
自定义线程Callable接口

public class MyCallable implements Callable 
  
    { 
   @Override  
     
   public String call() 
   throws Exception { Thread. 
   sleep( 
   2000); System. 
   out.println( 
   "MyCallable"); System. 
   out.println(Thread. 
   currentThread().getName()); System. 
   out.println( 
   "Callable"); 
   return null; } } 
  
自定义线程Runnable接口

public class MyRunnable implements Runnable{ @Override  public void run() { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()); System.out.println("Runnable"); } }
测试类

public class MainActivity extends AppCompatActivity { @Override  protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //创建线程池对象  ExecutorService service = Executors.newFixedThreadPool(2);//包含2个线程对象  //创建Runnable实例对象  MyRunnable myRunnable = new MyRunnable(); //自己创建线程对象的方式  //Thread t = new Thread(r);  //t.start(); ---> 调用MyRunnable中的run()  //从线程池中获取线程对象,然后调用MyRunnable中的run()  service.submit(myRunnable); //再获取个线程对象,调用MyRunnable中的run()  service.submit(myRunnable); service.submit(myRunnable); service.submit(myRunnable); //注意:submit方法调用结束后,程序并不终止,是因为线程池控制了线程的关闭。将使用完的线程又归还到了线程池中  //创建Callable实例对象  MyCallable myCallable = new MyCallable(); //从线程池中获取线程对象,然后调用MyRunnable中的run()  service.submit(myCallable); //再获取个教练  service.submit(myCallable); service.submit(myCallable); //关闭线程池  service.shutdown(); } }



四.线程的匿名内部类使用
使用线程的内匿名内部类方式,可以方便的实现每个线程执行不同的线程任务操作。
方式1:创建线程对象时,直接重写Thread类中的run方法




public class MainActivity extends AppCompatActivity { @Override  protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); new Thread() { @Override  public void run() { for (int x = 0; x < 50; x++) { Log.i("Thread", "===" + x); } } }.start(); for (int x = 0; x < 50; x++) { Log.i("Thread", "===" + x); } } }
方式2:使用匿名内部类的方式实现Runnable接口,重新Runnable接口中的run方法


public class MainActivity extends AppCompatActivity { @Override  protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Runnable runnable = new Runnable() { @Override  public void run() { for (int x = 0; x < 50; x++) { Log.i("Thread", "===" + x); } } }; Thread thread = new Thread(runnable); thread.start(); for (int x = 0; x < 50; x++) { Log.i("Thread", "===" + x); } } }
方式三:直接创建thread对象与Runnable对象

public class MainActivity extends AppCompatActivity { @Override  protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); new Thread(new Runnable() { @Override  public void run() { for (int x = 0; x < 50; x++) { Log.i("Thread", "===" + x); } } }).start(); for (int x = 0; x < 50; x++) { Log.i("Thread", "===" + x); } } }
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/224660.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月17日 上午11:26
下一篇 2026年3月17日 上午11:26


相关推荐

  • 全国计算机考试一级与ata,ata(ata证书是计算机一级吗)

    全国计算机考试一级与ata,ata(ata证书是计算机一级吗)2021年6月20日发(作者:665)12月计算机一级模拟训练2016年12月计算机一级模拟训练一、单项选择题:1、一个汉字的内码长度为2字节,其每个字节的二进制位的值分别为.A.0,0B.1,1C.1,0D.0,12、运算器的主要功能是.A.进行算术运算B.实现逻辑运算C.实现加法运算D.进行算术运算或逻辑运算3、计算机能直接识别和执行的语言是.A.机器语言B.高级语言C.汇编语言D.数据库语言…

    2022年7月14日
    30
  • silverlight技巧 获取鼠标滚轮事件 及 判断获取组合键的方法

    silverlight技巧 获取鼠标滚轮事件 及 判断获取组合键的方法

    2021年7月27日
    55
  • 数据结构知识整理

    数据结构知识整理基于严蔚敏及吴伟民编著的清华大学 C 语言版教材并结合网上相关资料整理 http www docin com p 2027739005 html 第一章 绪论 1 数据结构 是一门研究非数值计算的程序设计问题中计算机的操作对象以及他们之间的关系和操作等的学科 2 数据结构涵盖的内容 3 基本概念和术语 数据 对客观事物的符号表示 在计算机科学中是指所有能输入到计算机中并被计算

    2025年7月3日
    6
  • 登录双微信怎么登_windows设置多用户远程登录

    登录双微信怎么登_windows设置多用户远程登录QQ都能登录两个,为啥微信不行。其实微信也可以,让笔者来教教大家第一步:新建一个文本第二步:输入以下内容startD:\Tencent\WeChat\WeChat.exestartD:\

    2022年8月1日
    6
  • spring boot 过滤器_拦截器和过滤器的区别面试

    spring boot 过滤器_拦截器和过滤器的区别面试原文地址:https://www.tsanyang.top/share-detail/739784336139616256.html最近实现一个权限控制功能,想通过拦截器进行实现,当业务一切按预期一样完成,有一个特别控制需要再拦截器对参数进行解析使用,但是发现当我们再拦截器读取了输入流,再控制器是无法获取到参数的,这个是由于输入流只能被读取一次,然后通过问题搜索了一把,看见网上通过重写HttpServletRequestWrapper实现输入流读取后,再写入回去,这样解决控制器无法获取参数问题,故在此做记

    2022年8月23日
    11
  • ArcGIS10地理信息系统教程—从初学到精通—笔记(持续更新)

    ArcGIS10地理信息系统教程—从初学到精通—笔记(持续更新)arcgis10初学到精通—重要操作整理第二章ArcGIS快速入门1.设置相对路径37页2.选择要素48页3.超链接51页4.测量第三章地理数据库geodatabase有以下三种类型:文件地理数据库,个人地理数据库、arcsed数据库文件数据库:以文件夹的形式保存、管理。文件数据库可以由多个用户使用,但是同一数据在同一时间只能由一个用户编辑。个人…

    2022年6月16日
    45

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号