多线程基础体系知识清单

前言

本文会介绍Java中多线程与并发的基础,适合初学者食用。

线程与进程的区别

在计算机发展初期,每台计算机是串行地执行任务的,如果碰上需要IO的地方,还需要等待长时间的用户IO,后来经过一段时间有了批处理计算机,其可以批量串行地处理用户指令,但本质还是串行,还是不能并发执行。

如何解决并发执行的问题呢?于是引入了进程的概念,每个进程独占一份内存空间,进程是内存分配的最小单位,相互间运行互不干扰且可以相互切换,现在我们所看到的多个进程“同时"在运行,实际上是进程高速切换的效果。

那么有了线程之后,我们的计算机系统看似已经很完美了,为什么还要进入线程呢?如果一个进程有多个子任务,往往一个进程需要逐个去执行这些子任务,但往往这些子任务是不相互依赖的,可以并发执行,所以需要CPU进行更细粒度的切换。所以就引入了线程的概念,线程隶属于某一个进程,它共享进程的内存资源,相互间切换更快速。

进程与线程的区别:

  1. 进程是资源分配的最小单位,线程是CPU调度的最小单位。所有与进程相关的资源,均被记录在PCB中。

  2. 线程隶属于某一个进程,共享所属进程的资源。线程只由堆栈寄存器、程序计数器和TCB构成。

  3. 进程可以看作独立的应用,线程不能看作独立的应用。

  4. 进程有独立的地址空间,相互不影响,而线程只是进程的不同执行路径,如果线程挂了,进程也就挂了。所以多进程的程序比多线程程序健壮,但是切换消耗资源多。

Java中进程与线程的关系:

  1. 运行一个程序会产生一个进程,进程至少包含一个线程。

  2. 每个进程对应一个JVM实例,多个线程共享JVM中的堆。

  3. Java采用单线程编程模型,程序会自动创建主线程 。

  4. 主线程可以创建子线程,原则上要后于子线程完成执行。


线程的start方法和run方法的区别

区别

Java中创建线程的方式有两种,不管使用继承Thread的方式还是实现Runnable接口的方式,都需要重写run方法。调用start方法会创建一个新的线程并启动,run方法只是启动线程后的回调函数,如果调用run方法,那么执行run方法的线程不会是新创建的线程,而如果使用start方法,那么执行run方法的线程就是我们刚刚启动的那个线程。

程序验证

public class Main {
    public static void main(String[] args) {
        Thread thread = new Thread(new SubThread());
        thread.run();
        thread.start();
    }

}
class SubThread implements Runnable{

    @Override
    public void run() {
        // TODO Auto-generated method stub
        System.out.println("执行本方法的线程:"+Thread.currentThread().getName());
    }

}

 

多线程基础体系知识清单


Thread和Runnable的关系

Thread源码

多线程基础体系知识清单

Runnable源码

多线程基础体系知识清单

区别

通过上述源码图,不难看出,Thread是一个类,而Runnable是一个接口,Runnable接口中只有一个没有实现的run方法,可以得知,Runnable并不能独立开启一个线程,而是依赖Thread类去创建线程,执行自己的run方法,去执行相应的业务逻辑,才能让这个类具备多线程的特性。

使用继承Thread方式和实现Runable接口方式分别创建子线程

使用继承Thread类方式创建子线程

public class Main extends Thread{
    public static void main(String[] args) {
        Main main = new Main();
        main.start();
    }
    @Override
    public void run() {
        System.out.println("通过继承Thread接口方式创建子线程成功,当前线程名:"+Thread.currentThread().getName());
    }

}

运行结果:

多线程基础体系知识清单

使用实现Runnable接口方式创建子线程

public class Main{
    public static void main(String[] args) {
        SubThread subThread = new SubThread();
        Thread thread = new Thread(subThread);
        thread.start();
    }

}
class SubThread implements Runnable{

    @Override
    public void run() {
        // TODO Auto-generated method stub
        System.out.println("通过实现Runnable接口创建子线程成功,当前线程名:"+Thread.currentThread().getName());
    }

}

运行结果:

多线程基础体系知识清单

使用匿名内部类方式创建子线程

public class Main{
    public static void main(String[] args) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                // TODO Auto-generated method stub
                System.out.println("使用匿名内部类方式创建线程成功,当前线程名:"+Thread.currentThread().getName());
            }
        });
        thread.start();
    }
}

运行结果:

多线程基础体系知识清单

关系

  1. Thread是实现了Runnable接口的类,使得run支持多线程。

  2. 因类的单一继承原则,推荐使用Runnable接口,可以使程序更加灵活。


如何实现处理多线程的返回值

通过刚才的学习,我们知道多线程的逻辑需要放到run方法中去执行,而run方法是没有返回值的,那么遇到需要返回值的状况就不好解决,那么如何实现子线程返回值呢?

主线程等待法

通过让主线程等待,直到子线程运行完毕为止。

实现方式:

public class Main{
    static String str;
    public static void main(String[] args) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                str="子线程执行完毕";
            }
  
  • 18
    点赞
  • 91
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值