1.线程的概念

提到线程,我们就不得不提到另外一个与之相似的概念:进程。何为进程?进程就是一个程序一次动态的执行过程,即计算机中一个任务的执行。在使用计算机的过程中,例如:打开酷狗软件听音乐,登录QQ与好友互动,Java虚拟机的启动等等,都对应着计算机中的一个个进程,进程是操作系统进行资源分配的基本单位
那么什么又是线程呢?如果进程是一个大的任务,那么线程就是这个大任务中一个个具体的子任务,我们可以把线程看成是一个更加轻量级的进程。在使用酷狗软件时,我们既可以一边播放音乐,一边下载歌曲,同时还可以设置背景颜色,这些一个个的具体操作就是线程,线程是CPU调度的基本单位

2.线程的创建

创建线程有两种常见的方式:继承java.lang.Thread类和实现Runnable接口
继承Thread类,重写run方法,在run方法中定义需要执行的任务

public class MyThread extends Thread {
    @Override
    public void run(){}  
}
Thread thread = new MyThread();
thread.start(); 

实现Runnable接口,重写run方法,在run方法中定义需要执行的任务

Runnable r = () -> {
  // 具体实现
};
Thread thread = new Thread(r);
thread.start();

创建线程的两种方式的比较
相比于第一种继承Thread类创建线程的方式,更加推荐使用第二种方式,因为第二种方式实现了线程的创建与具体执行的任务之间的解耦,并且在实现Runnable接口时同时可以继承其它的类

3.线程的状态

线程有6种状态:

  • NEW(新建)
  • RUNNABLE(可运行)
  • BLOCKED(阻塞)
  • WAITING(等待)
  • TIMED_WAITING(计时等待)
  • TERMINATED(被终止)
    线程各个状态的转换:
    线程状态转换.png

    4.线程常用方法

  • void start()
    调用start()方法将会启动一个新的线程,当该线程获得CPU执行权后,将引发调用run()方法,执行用户定义的子任务
  • void run()
    当启动一个新的线程并获得CPU执行权后,便自动调用run()方法去执行具体的子任务。 注意,如果直接调用run()方法,那么系统将不会启动一个新的线程,而是将run()方法作为一个普通方法运行
  • static native void sleep(long millis)
    sleep()方法让线程休眠给定的时间,同时放弃CPU的执行权,此时线程进入TIMED_WAITING状态
    注意,如果当前线程持有某个对象的锁,调用sleep()方法不会释放该锁
  • static native void yield()
    调用yield方法会让当前线程放弃CPU的执行权,它跟sleep方法类似,同样不会释放锁,但是yield不能控制具体的交出CPU的时间
    另外,yield方法只能让拥有相同优先级的线程有获取CPU执行权的机会
    注意,调用yield方法并不会让线程进入阻塞状态,而是让线程重回可运行状态
  • final void join()
    调用thread.join()方法,当前线程将等待thread执行完毕,如果调用的是指定了时间参数的join方法,则等待指定的时间
  • void interrupt()
    向线程发送中断请求,线程的中断状态将被置为true。如果目前该线程被一个sleep调用阻塞,那么InterruptedException异常被抛出
  • boolean isInterrupted()
    测试线程是否被终止,不改变中断状态
  • static boolean interrupted()
    测试当前线程(正在执行这一命令的线程)是否被中断
    注意:调用该方法将会使当前线程的中断状态重置为false

版权声明:本文为liantdev原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/liantdev/p/10289731.html