一,首先提到线程就会想起进程,那么他们有什么区别呢?

1,什么是进程?
进程是操作系统结构的基础,是程序在一个数据集合上运行的过程,是系统进行资源分配和调度的基本单位。进程可以被看作程序的实体,同样,它也是线程的容器。
比如:任务管理器里面的运行的exe程序,手机运行的任何一款APP。

2,什么是线程?
是操作系统调度的最小单元,也叫作轻量级进程。在一个进程中可以创建多个线程,这些线程都拥有各自的计数器、堆栈和局部变量等属性,并且能够访问共享的内存变量
比如:浏览器打开了多个网页。这个浏览器看做是进程,而里面的子网页,就可以看做是线程。
在android代码里面:比如:网络请求,文件查询等复杂操作一般都写在子线程。

3,为什么使用多线程?
• 使用多线程可以减少程序的响应时间。如果某个操作很耗时,或者陷入长时间的等待,此时程序将不
会响应鼠标和键盘等的操作,使用多线程后可以把这个耗时的线程分配到一个单独的线程中去执行,从而
使程序具备了更好的交互性。

• 与进程相比,线程创建和切换开销更小,同时多线程在数据共享方面效率非常高。

• 多CPU或者多核计算机本身就具备执行多线程的能力。如果使用单个进程,将无法重复利用计算机资
源,这会造成资源的巨大浪费。在多CPU计算机中使用多线程能提高CPU的利用率。

• 使用多线程能简化程序的结构,使程序便于理解和维护。

二,线程的状态

Java线程在运行的声明周期中可能会处于6种不同的状态,这6种线程状态分别为如下所示。
New:新创建状态。线程被创建,还没有调用 start 方法,在线程运行之前还有一些基础工作要做。
Runnable:可运行状态。一旦调用start方法,线程就处于Runnable状态。一个可运行的线程可能正在
运行也可能没有运行,这取决于操作系统给线程提供运行的时间。
Blocked:阻塞状态。表示线程被锁阻塞,它暂时不活动。
Waiting:等待状态。线程暂时不活动,并且不运行任何代码,这消耗最少的资源,直到线程调度器
重新**它。
Timed waiting:超时等待状态。和等待状态不同的是,它是可以在指定的时间自行返回的。
Terminated:终止状态。表示当前线程已经执行完毕。导致线程终止有两种情况:第一种就是run方
法执行完毕正常退出;第二种就是因为一个没有捕获的异常而终止了run方法,导致线程进入终止状态。

Android 线程基础详解(进阶之光阅读笔记)
如图 所示,线程创建后,调用 Thread 的 start 方法,开始进入运行状态,当线程执行wait 方法后,
线程进入等待状态,进入等待状态的线程需要其他线程通知才能返回运行状态。超时等待相当于在等待状
态加上了时间限制,如果超过时间限制,则线程返回运行状态。当线程调用到同步方法时,如果线程没有
获得锁则进入阻塞状态,当阻塞状态的线程获取到锁时则重新回到运行状态。当线程执行完毕或者遇到意
外异常终止时,都会进入终止状态

三,线程的使用
多线程的实现一般有以下3种方法,其中前两种为最常用的方法。
1.继承Thread类,重写run()方法Thread本质上也是实现了Runnable接口的一个实例。
需要注意的是调用start()方法后并不是立即地执行多线程的代码,而是使该线程变为可运行态,什么时候运行多线程代码是由操作系统决定的。
以下是其主要步骤:
(1)定义Thread类的子类,并重写该类的run方法,该run方法的方法体就代表了线程要完成的任务。因 此,run()方法被称为执行体。
(2)创建Thread子类的实例,即创建了线程对象。
(3)调用线程对象的start()方法来启动该线

public class MyThread extends Thread {
    @Override
    public void run() {
        Log.e("这是第一种方式", "");
    }
}
  public void startMyThread() {
        MyThread myThread = new MyThread();
        myThread.start();
    }

2.实现Runnable接口,并实现该接口的run()方法
以下是其主要步骤:
(1)自定义类并实现Runnable接口,实现run()方法。
(2)创建Thread子类的实例,用实现Runnable接口的对象作为参数实例化该Thread对象。
(3)调用Thread的start()方法来启动该线程

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        Log.e("方式2","");
    }
}
  public void startMyRunnable() {
        MyRunnable myRunnable = new MyRunnable();
        Thread thread = new Thread(myRunnable);
        thread.start();
    }

3.实现Callable接口,重写call()方法
Callable接口实际是属于Executor框架中的功能类,Callable接口与Runnable接口的功能类似,但提供了
比Runnable更强大的功能,主要表现为以下3点:
(1)Callable可以在任务接受后提供一个返回值,Runnable无法提供这个功能。
(2)Callable中的call()方法可以抛出异常,而Runnable的run()方法不能抛出异常。
(3)运行Callable可以拿到一个Future对象,Future对象表示异步计算的结果,它提供了检查计算是否
完成的方法。由于线程属于异步计算模型,因此无法从别的线程中得到函数的返回值,在这种情况下就可
以使用 Future 来监视目标线程调用 call()方法的情况。但调用 Future的get()方法以获取结果时,当前
线程就会阻塞,直到call()方法返回结果

    public class MyCallble implements Callable{

        @Override
        public Object call() throws Exception {
            return "Hello";
        }
    }
  public void startMyCallble(){
        MyCallble myCallble=new MyCallble();
        ExecutorService executorService=Executors.newScheduledThreadPool();
        Future mFuture=executorService.submit(myCallble);
        try {
            mFuture.get();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

当我在编辑器里面写的时候,这第三个方式的代码是错误的。
附上一张正解的图Android 线程基础详解(进阶之光阅读笔记)
第三种方式推荐看这篇文章

4,中断

当线程的run方法执行完毕,或者在方法中出现没有捕获的异常时,线程将终止。在Java早期版本中有
一个stop方法,其他线程可以调用它终止线程,但是这个方法现在已经被弃用了。interrupt 方法可以用来请
求中断线程。当一个线程调用 interrupt 方法时,线程的中断标识位将被置位(中断标识位为true),线程会
不时地检测这个中断标识位,以判断线程是否应该被中断。要想知道线程是否被置位,可以调用
Thread.currentThread().isInterrupted(),

      MyRunnable myRunnable = new MyRunnable();
        Thread thread = new Thread(myRunnable);
        thread.start();
        //中断
        thread.interrupt();

关于,创建线程 还有一种匿名创建的方式,不过本质也是实现Runnable接口。

   new  Thread(new Runnable() {
            @Override
            public void run() {
                
            }
        }).start();

相关文章: