Android 线程基础

4.1线程基础

4.1.1 进程和线程

  1. 什么是线程

    进程可以被看作程序的实体;同样,它也是线程的容器。

  2. 什么是线程

    windows任务管理器一个进程下面有很多线程,线程是操作系统调度的最小单位,也叫作轻量级进程。在一个进程中可以创建多个线程,这些线程都拥有各自的计数器、堆栈和局部变量等属性,并且能过访问共享的内存变量。

  3. 为何使用多线程

    • 使用线程减少程序的响应时间

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

    • 多CPU 或者多核的计算机本身就具备执行多线程的能力。

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

4.1.2 线程的状态

Java线程在运行的生命周期中可能处于 6 中不同的状态,这 6 中不同线程如下所示。

  • New:新创建状态,线程被创建,还没有调用 start 方法,在线程运行之前还有一些基础工作要做。

  • Runable:可运行状态。一旦调用 start 方法,线程就处于 Runnable 状态。一个可运行的线程可能正在运行,也可能没有运行,这取决于操作系统线程提供运行的时间。

  • Blocked:阻塞状态。表示线程被锁阻塞,它暂时不活动。

  • Waiting:等待状态。线程暂时不活动,并且不运行任何代码,这消耗最少的资源,直到线程调度重新激活它。

  • Timed waiting:超时等待状态。和等待状态不同的是,它是可以在指定的时间自行返回的。

  • Terminated:终止状态。表示当前线程已经执行完毕。导致线程终止有两种情况:第一种就是 run 方法执行完毕正常退出;第二种就是因为一个没有捕获的异常而终止了 run 方法,导致线程进入终止状态。

4.1.3 创建线程

  1. 继承 Thread 类,重写 run 方法

    public class TestThread extends Thread {
    ​
        @Override
        public void run() {
            super.run();
            System.out.println("Hello World");
        }
    }
    TestThread testThread = new TestThread();
    testThread.start();

  2. 实现 Runnbale 接口,并实现该接口的 run 方法

    public class TestRunnable implements Runnable {
        @Override
        public void run() {
            System.out.println("Hello World");
        }
    }
    TestRunnable testRunnable = new TestRunnable();
    Thread thread = new Thread(testRunnable);
    thread.start();

  3. 实现Callable 接口,重写 call 方法

    Callable 接口实现是属于 Executor 框架中的功能类, Callable 接口与 Runable 接口的功能类似,但提供了比 Runable 接口更强大的功能,主要表现以下 3 点:

    • Callable 可以在任务接收后提供一个返回值,Runable无法提供这个功能。

    • Callable 中的 call 方法可以抛出异常,而 Runable 的 run 方法不能抛出异常。

    • 运行 Callable 可以拿到一个 Futrue 对象: Future 对象表示异步计算的结果,他提供了检测计算是否完成的方法。由于线程属于异步计算模型,因此无法从别的线程中得到函数的返回值,在这种情况下就可以使用 Furture 来监视目标线程调用 call 方法的情况。但调用 Future 的 get 方法以获取结果时,当前线程就会被阻塞,直到 call 方法返回结果。

    public class TestCallable implements Callable {
        @Override
        public String call() throws Exception {
            return "Hello word";
        }
    }
    TestCallable testCallable = new TestCallable();
    ExecutorService executorService = Executors.newSingleThreadExecutor();
    Future future = executorService.submit(testCallable);
    try {
        System.out.println(future.get());
    } catch (Exception e) {
        e.printStackTrace();
    }

4.1.4 理解中断

当一个线程调用 interrupt 方法时,线程的中断标识为将被置位(中断标识为true),线程会不时地检测这个中断标识位,以判断线程是否应该被中断。要想知道线程是否被置位,可以调用 Thread.currentThread().isInterrupted() ,如下所示

while(!Thread.currentThread()).isInterrupted()){
    // do something
}

还可以调用 Thread.interrupted() 来对中断标识位进行复位。但是如果一个线程被阻塞,就无法检测中断状态。如果一个线程处于阻塞,就无法检测中断状态。如果一个线程处于阻塞状态,那么线程在检查中断标识位时若发现中断标识位为true,则会在阻塞方法调用处抛出 InterruptedException异常,并且在抛出异常前将线程的中断标识位复位,即重新设置为 false 。需要注意的是被中断的线程不一定会终止,中断线程是为了引起线程的注意,被中断的线程就可以决定如何去响应中断。如果是比较重要的线程,则不会理会中断;而大部分情况是线程将中断作为一个终止的请求。另外,不要在底层代码里捕获 InterruptedException 异常后不做处理,如下所示:

void myTask(){
  ...
  try{
      sleep(50)
  }catch(InterruptedException e){
    
  }
}

如果你不知道抛出 InterruptedException 异常后如何处理,这里介绍两种合理的处理方式。

(1)在 catch 子句中,调用 Thread.currentThread.interrupt()来设置中断状态(因为抛出异常后中断标识为会复位),让外界通过判断 Thread.currentThread().isInterrupted()来决定是终止线程还是继续下去,应该这样做:

void myTask(){
		...
		try{
				sleep(50)
		}catch(InterrupedException e){
				Thread.currentThread().interrupt();
		}
		...
}

(2)更好的做法就是,不使用 try 来捕获这样的异常,让方法直接抛出,这样调用者可以捕获这个异常,如下所示:

void myTask() throw InterruptedException{
  		sleep(50)
}

4.1.5 安全的中断异常

1.用中断来终止线程

public class StopThread {
    public static void main(String[] args) throws InterruptedException {
        // 1.用中断来终止线程
        MoonRunner runner = new MoonRunner();
        Thread thread = new Thread(runner, "MoonThread");
        thread.start();
        TimeUnit.MILLISECONDS.sleep(10);
        thread.interrupt();
    }
}
public class MoonRunner implements Runnable {
    private long i;
    @Override
    public void run() {
        while (!Thread.currentThread().isInterrupted()) {
            i++;
            System.out.println("i=" + i);
        }
        System.out.println("stop");

    }
}

2.使用 boolean 值终止

public class StopThread2 {
    public static void main(String[] args) throws InterruptedException {
        MoonRunner2 moonRunner2 = new MoonRunner2();
        Thread thread = new Thread(moonRunner2, "MoonThread");
        thread.start();
        TimeUnit.MILLISECONDS.sleep(10);
        moonRunner2.cancle();
    }
}
public class MoonRunner2 implements Runnable {

    private long i;
    private volatile boolean on = true;

    @Override
    public void run() {
        while (on) {
            i++;
            System.out.println("i=" + i);
        }
        System.out.println("stop");
    }

    public void cancle() {
        on = false;
    }
}

END

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

仰延Elliot

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值