JAVA多线程(一):线程与进程的关系、线程的创建及线程状态的转换过程

说明:这篇博客是我读《JAVA并发编程之美》后的一个总结。如有侵权请联系删除。同时说明以下内容仅代表个人观点,如果有不清除或是有错误的地方,欢迎大家批评指正!!!

目录

1.进程与线程的基础概念

什么是进程?什么是线程?

进程和线程在JAVA中的表现

2.JAVA中如何创建线程?他们的优缺点是什么?

3.JAVA中的线程有哪些状态?

他们之间是怎么转换的?

转换涉及方法详解:


1.进程与线程的基础概念

  • 什么是进程?什么是线程?

答:进程是操作系统分配和调度资源的最小单位,而对于CPU的资源的分配是以线程来划分的。线程是进程中的一个实体,线程属于进程,一个进程可以有多个线程。举个简单的例子:进程可以理解为一个工厂,而线程就是工厂中的一个个的流水线。

  • 进程和线程在JAVA中的表现

当我们运行main方法是就启动了一个JVM(java虚拟机)进程,main方法就是该进程中的一个线程,也称主线程。

其大致表现如下图:

该图中绿色部分代表各个线程共享的部分,红色的部分则代表各个线程独有的部分。

:主要存放的是new操作创建的对象实例。

方法区:存放JVM加载的类,常量及静态变量等信息。

程序计数器:用于记录下一条指令的地址(或者理解为代码执行的位置)。

:用于存储该线程的局部变量(线程私有),栈帧。

2.JAVA中如何创建线程?他们的优缺点是什么?

JAVA中一共有3种创建线程的方式:

public class CreateThread1 {
    // 1.继承Thread类的方式
    private static class InheritThread extends Thread {
        @Override
        public void run() {
            System.out.println("InheritThread!");
        }
    }
    
    // 2.实现Runnable接口
    private static class ImplementRunnable implements Runnable {
        @Override
        public void run() {
            System.out.println("ImplementRunnable!");
        }
    }

    // 3.使用FutureTask
    private static class ImplementCallable implements Callable<String> {
        @Override
        public String call() throws Exception {
            return "Hello world!";
        }
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 1.继承Thread类的方式
        new InheritThread().start();
        // 2.实现Runnable接口的方式
        new Thread(new ImplementRunnable()).start();
        // 3.使用FutureTask的方式
        FutureTask<String> stringFutureTask = new FutureTask<>(new ImplementCallable());
        new Thread(stringFutureTask).start();
        // 输出FutureTask的方式的返回值
        System.out.println(stringFutureTask.get());
    }
}

小结:使用继承方式的好处是方便传参,你可以在子类里面添加成员变量,通过set方法设置参数或者通过构造函数进行传递,而如果使用Runnable方式,则只能使用主线程里面被声明为final的变量。不好的地方是Java不支持多继承,如果继承了Thread类,那么子类不能再继承其他类,而Runable则没有这个限制。前两种方式都没办法拿到任务的返回结果,但是Futuretask方式可以。

3.JAVA中的线程有哪些状态?

共有6中状态:

    NEW:新建

    RUNNABLE:运行

    WAITING:等待

    TIMED_WAITING:有时限的等待,超过指定时间后自行返回

    BLOCKED:阻塞状态

    TERMINATED:终止

  • 他们之间是怎么转换的?

  • 转换涉及方法详解:

(1)唤醒与等待

等待:wait()、wait(long timeout)、wait(long timeout, int nanos)。这三个方法是Object类提供的方法,即所有对象都能使用。其中核心方法为红色标注的方法。该过程会释放掉该共享变量的锁,若没有获取到共享变量的锁而调用其wait方法会报IllegalMonitorStateException异常,若在等待的过程中被打断会抛出InterruptedException。

    wait():内部调用的是wait(0)代表一直等待。

    wait(long timeout):代表超过timeout毫秒后会自动返回,该方法为native方法。

    wait(long timeout, int nanos):其内部也是调用的wait(long timeout),加了对与nanos的判断(0-999999)在这个范围内是timeout + 1,否则抛出异常。

唤醒:notify()、notifyAll()。这两个方法是Object类提供的方法,用于唤醒等待的线程。

    notify():会随机唤醒一个因争夺当前共享变量失败而阻塞的线程。

    notifyAll():会唤醒所有因争夺当前共享变量失败(在调用该方法前)而阻塞的线程。

(2)等待线程执行终止的方法join

join()、join(long millis)、join(long millis, int nanos)。这三个方法是Thread类提供的方法。用于等待线程执行终止。其中核心方法为红色标注的方法,其内部调用的是wait方法。若在等待的过程中被打断会抛出InterruptedException,就不再展开赘述了。

(3)让线程睡眠的方法

sleep(long millis)、sleep(long millis, int nanos)。这两个方法是Tread类提供的静态方法。用于当前线程进入睡眠。其中核心方法为红色标注的方法,该方法为native方法。睡眠过程中不会释放当前线程获取到锁,若在睡眠的过程中被打断会抛出InterruptedException。

(4)让出CPU执行权的方法yield

yield(),这个方法是Thread类提供的方法,其为native方法,会交出当前CPU的使用权,但是会立刻进入到下一轮的争抢中,也就是说下次争抢到的CPU使用权的线程可能还是该线程。

(5)线程的中断

interrupt()、isInterrupted()、interrupted()、isInterrupted(boolean ClearInterrupted)。这四个方法都是跟中断线程相关的方法。其中红色标注的方法是核心方法。

    interrupt():该方法中用于给调用该方法的线程设置中断标记。但是如果线程正在运行,并不真正的打断线程的运行,这里只是设置了标记而已。需要和其他方法配合使用。

    isInterrupted(boolean ClearInterrupted):该方法是一个私有的native方法,用于判断该线程的中断标记为true,同时对标记进行清除(当ClearInterrupted变量为true时)

    interrupted():该方法是Thread类的静态方法,其内部代码如下,这里尤其要注意的是这里是对当前线程的中断标记进行判断,并清除该标记。

public static boolean interrupted() {
    return currentThread().isInterrupted(true);
}

    isInterrupted():该方法是Thread类的一个方法,用于判断线程的中断标记是否为true。这里也是调用的isInterrupted(boolean ClearInterrupted),但是参数为false,所以不对标记进行清除。

关于图中使用LockSupprot的方法不在本次分享中进行详细说明。后续会有专门针对与它的讲解。

如果有不清楚或是错误的地方,欢迎大家下方留言一起讨论!!!同时该系列会持续分享,如果希望看到后续的内容也可以关注一下😁!!!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值