目录

一、概念

1.什么是线程?

2.使用多线程的意义

3.线程 vs 进程

4.java线程与操作系统线程的关系

二、第一个java线程

三、面试高频:创建线程的方式

1.创建 Thread 子类

2.实现 Runnable 接口

3.匿名内部类创建Thread/Runnable子类对象

4.lambda表达式创建Runnable


一、概念

1.什么是线程?

        线程实际上是一个“ 执行流 ” ,一个程序通常需要多个线程来执行任务,每个线程都会按照顺序执行自己的代码,多个线程“ 同时 ”执行着多份代码,也就是并发编程

问:那么何为并发? 何为并行?

        首先需要清楚一个方向,即并发和并行的核心区别不在于是否在同一个进程中,而实是否真正地同时进行。

  • 并发:多个线程交替使用cpu,宏观上看是同时进行,但微观上是串行执行。
  • 并行:多个线程在多核cpu上同时执行,是真正意义上的同时进行。

2.使用多线程的意义

  • 提高cpu的利用率

        早期的单核cpu发展遇到了瓶颈,于是引进了多核cpu,而多线程能够让多个线程在多个cpu核心上执行,让cpu的多个核心同时工作,提升了计算效率。

  • 避免阻塞等待,防止页面卡顿

        有些特殊的任务场景需要“ 等待IO ”,为了能够让cpu在等待IO的时间里做一些其他的事情,多线程可以把较耗时间的操作放到后台运行,前台线程(即当前使用cpu的线程)继续响应用户的操作。

3.线程 vs 进程

        一个进程中至少要有一个线程来执行任务,故进程是包含线程的。并且我们知道实现并发编程能够提高cpu的效率,多进程和多线程都可以实现并发编程,但为何多线程是更优解?其实原因就在于对于进程的创建和销毁的开销相较于线程来说是极大的。

        根据线程和进程的区别,有以下总结:

  • 进程包含线程。
  • 线程在 创建销毁调度上的时间耗费相较于进程来说是更少的。
  • 线程和进程还有一个区别在于,同一个进程中的多个线程是共享内存空间的,但多进程是分别占用的不同的内存空间的
  • 进程之间是互不影响的,但一个线程出问题可能会导致整个进程奔溃。

4.java线程与操作系统线程的关系

        线程其实是操作系统中的说法,操作系统内核实现了线程机制,并针对用户层提供了以下API供用户使用,java类中的Thread线程类就可以看作是对操作系统提供的API进行了进一步的抽象和封装。.

二、第一个java线程

  •   每个线程都是一个单独的“ 执行流 ”
  •   多个线程实现“ 并发执行 ”
public class ThreadTest {
    static class Mythread extends Thread{
        @Override
        public void run() {
            while(true){
                System.out.println(Thread.currentThread().getName());
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }
    }
    public static void main(String[] args) {
        Thread t=new Mythread();
        t.start();

        while(true){
            System.out.println(Thread.currentThread().getName());
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

三、面试高频:创建线程的方式

1.创建 Thread 子类

步骤:创建Thread子类,重写run方法 —>  创建子类的上转型对象 —>  调用start()方法

public class CreateThread1 {

    //创建Thread子类
    static class MyThread extends Thread{
        //重写run方法
        @Override
        public void run() {
            System.out.println("这是线程1");
        }
    }

    public static void main(String[] args) {
        Thread t1= new Mythread();//上转型对象
        t1.start();//调用start
    }
}

2.实现 Runnable 接口

步骤:实现Runnable接口,重写run方法 —>  创建Thread实例对象,Runnable对象作为构造方法参数 —>  调用start()方法

public class CreateThread2 {
    
    //实现Runnable接口
    static class MyRunnable implements Runnable{
        //重写run方法
        @Override
        public void run() {
            System.out.println("这是线程2");
        }
    }

    public static void main(String[] args) {
        Thread t2= new Thread(new MyRunnable());//参数
        t2.start();//调用start
    }
}

3.匿名内部类创建Thread/Runnable子类对象

public class CreateThread3 {

    public static void main(String[] args) {
        //使用匿名类创建Thread 子类对象
        Thread t3=new Thread(){
            @Override
            public void run() {
                System.out.println("这是 线程3");
            }
        };
        
        //使用匿名类创建Runnable 子类对象
        Thread t4=new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("这是 线程4");
            }
        });
    }
}

4.lambda表达式创建Runnable

public class CreateThread4 {

    public static void main(String[] args) {
        Thread t5=new Thread(()->{
            System.out.println("这是线程5");
        });
    }
}

        由此可见,最简便的方式当属第四种的lambda表达式,在真正的开发过程中用到最多的也是第四种。

         以上就是对于初学者认识线程,理解线程的分享,下期再见哦。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐