线程基础

一、线程:

1、线程和进程:

进程:是系统进行资源分配的基本单位,例如Window管理器中某个exe程序:qq.exe、studio.exe。在android系统中,一般表示的是一个应用程序,例如邮件、相机等应用。

线程:操作系统调度的最小单位,比如多个线程有的请求数据,有的更新ui,有的操作数据库。线程拥有各自的计数器、堆栈、局部变量等。

线程的意义:如果所有操作都在一个线程执行,会导致效应速度慢,效率低。如果将耗时操作放在其他线程中执行,减少了主线程响应时间,会有更好的交互。

进程和线程的关系:一个进程有多个线程,一个应用可以开启多个线程进行工作。

2、线程的状态:

  • New: 创建状态,线程刚创建,还没有调用start方法。
  • Runnable:可运行状态,调用了start方法后线程在执行run方法且没有阻塞时状态为Runnable,不过,Runnable不代表CPU一定在执行该线程的代码,可能正在执行也可能在等待操作系统分配时间片。
  • Blocked: 阻塞状态,表示该线程被锁阻塞。例如其他线程持有锁,该线程在等待其他线程将锁释放。
  • Waiting:等待状态,线程没运行任何代码,需要线程调度器重新激活。例如线程A调用wait方法进行等待,这时候需要其他线程调用notify或notifyAll方法激活线程A。
  • Timed waiting:超时等待状态,和等待状态的区别:在等待指定时间后自动激动。
  • Terminated:终止状态,当前线程执行完毕。比如run方法执行完了,或者执行过程中遇到异常终止线程。
如图所示:


3、常用方法:

(1)获取id和name:

public long getId()public final String getName()复制代码

(2)获取和设置优先级:

public final void setPriority(int newPriority)public final int getPriority()复制代码

(3)会让当前线程睡眠指定的时间,单位是毫秒。 睡眠期间,该线程会让出CPU, 睡眠期间,线程可以被中断,如果被中断,sleep会抛出InterruptedException。

public static native void sleep(long millis) throws InterruptedException;
复制代码

(4)让调用join的线程等待该线程结束, 在等待线程结束的过程中,这个等待可能被中断,如果被中断,会抛出InterruptedException。

public final void join() throws InterruptedException
复制代码

(5)wait:

public final void wait() throws InterruptedException
public final native void wait(long timeout) throws InterruptedException;复制代码
wait的具体过程:
  • 把当前线程放入条件等待队列,释放对象锁,阻塞等待,线程状态变为WAITING或TIMED_WAITING
  • 等待时间到或被其他线程调用notify/notifyAll从条件队列中移除,这时,要重新竞争对象锁
    • 如果能够获得锁,线程状态变为RUNNABLE,并从wait调用中返回
    • 否则,该线程加入对象锁等待队列,线程状态变为BLOCKED,只有在获得锁后才会从wait调用中返回

(6)notify/notifyAll:

public final native void notify();
public final native void notifyAll();
复制代码

notify就是从条件队列中选一个线程,将其从队列中移除并唤醒,notifyAll会移除条件队列中所有的线程并全部唤醒。  

(7)interrupted方法:

注:停止一个线程的主要机制是中断,中断并不是强迫终止一个线程,它是一种协作机制,是给线程传递一个取消信号,但是由线程来决定如何以及何时退出。

public boolean isInterrupted()
public void interrupt()
public static boolean interrupted()
复制代码

  • isInterrupted:返回对应线程的中断标志位是否为true。
  • interrupted:返回当前线程的中断标志位是否为true,还有就是清空中断标志位。也就是说,连续两次调用interrupted(),第一次返回的结果为true,第二次一般就是false
  • interrupt:表示请求中断对应的线程,此时线程中断标志位置为true,线程会不断检测此标志位。
 注:如线程被阻塞, 检测中断标志位为true,会抛出InterrputedException异常,并将中断标志位复位,重新置为false。

线程自身处理中断:

public class MyRunnable implements Runnable{
    int i = 0;
    @Override
    public void run() {
        while (!Thread.currentThread().isInterrupted()){
            System.out.print(++i);
        }
        //如果线程执行中调用interrupt方法,输出然后结束
        System.out.print("interrupt");
    }
}复制代码


二、线程创建:

1、继承Thread类,重写run方法:

class Thread implements Runnable {复制代码

Thread内部实现了Runnable接口

public class MyThread extends Thread {
    @Override
    public void run() {
        super.run();
        System.out.print(getName());
    }
}
复制代码

MyThread thread = new MyThread();
thread.start();复制代码

创建Thread子类实例,然后调用start方法

2、实现runnable接口,实现run方法

public class MyRunnable implements Runnable{
    @Override
    public void run() {
        System.out.print("hello");
    }
}复制代码

MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
thread.start();复制代码

  • 实现Runnable接口,实现run方法
  • 创建Thread实例对象,将实现了Runnable的实例对象以参数形式传入
  • 调用Thread对象的start方法

3、实现Callable接口,实现call方法:

public class MyCallback implements Callable<Integer> {

    @Override
    public Integer call() throws Exception {
        return 2;
    }
}复制代码

MyCallback callback = new MyCallback();
Future<Integer> future = Executors.newSingleThreadExecutor().submit(callback);
try {
    System.out.print(future.get());
} catch (InterruptedException e) {
    e.printStackTrace();
} catch (ExecutionException e) {
    e.printStackTrace();
}复制代码

  • 实现Callback接口,实现run方法
  • 实例化MyCallback对象,通过参数的形式传递给ExecutorService的submit方法
  • 最终通过调用Future的get方法获取到任务执行完毕的返回值

Future对象:

public interface Future<V> {
    boolean cancel(boolean var1);

    boolean isCancelled();

    boolean isDone();

    V get() throws InterruptedException, ExecutionException;

    V get(long var1, TimeUnit var3) throws InterruptedException, ExecutionException, TimeoutException;
}复制代码

  • 运行 Callable 任务可以拿到一个 Future 对象,表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。通过 Future 对象可以了解任务执行情况,可取消任务的执行,还可获取执行结果;

Runnable和Callable的区别:

  • Callable 接口下的方法是 call(),Runnable 接口的方法是 run();
  • Callable 的任务执行后可返回值,而 Runnable 的任务是不能返回值的;
  • call() 方法可以抛出异常,run()方法不可以的;

总结:一般需要返回值,比如在线程中读取数据库数据,可以用Callback创建线程,如果不需要返回值,比如写入数据库,可以使用Thread或Runnable去创建线程。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值