什么是线程?

本文详细介绍了线程的概念,为何需要线程,以及Java中的线程与操作系统线程的关系。讲解了通过继承Thread类、实现Runnable接口、匿名内部类和Lambda表达式创建线程的方法,并对比了这些方式。同时讨论了进程与线程的区别,包括内存共享、资源管理和并发性能。
摘要由CSDN通过智能技术生成

正文

线程是什么

为什么要有线程

进程和线程的关系与区别

Java 的线程 和 操作系统线程 的关系

创建线程的方法

方法1 继承 Thread 类

方法2 实现Runnable接口

方法3 匿名内部类创建 Thread 子类对象

方法4 匿名内部类创建 Runnable 子类对象

方法5 lambda 表达式创建 Runnable 子类对象(常用)

总结


正文

线程是什么

一个线程就是一个 "执行流". 每个线程之间都可以按照顺序执行自己的代码. 多个线程之间 "同时" 执行着多份代码。

线程也可以称为“轻量级”进程,它在进程的基础上做出了改进。

既保持了独立调度执行这样的“并发支持”,又同时省去“分配资源”“释放资源”带来的额外开销。

线程是系统调度执行的基本单位。

设想如下场景: 一家公司要去银行办理业务,既要进行财务转账,又要进行福利发放,还得进行缴社保。 如果只有张三一个会计就会忙不过来,耗费的时间特别长。为了让业务更快的办理好,张三又找来两 位同事李四、王五⼀起来帮助他,三个人分别负责⼀个事情,分别申请一个号码进行排队,自此就有 了三个执行流共同完成任务,但本质上他们都是为了办理⼀家公司的业务。 此时,我们就把这种情况称为多线程,将一个大任务分解成不同小任务,交给不同执行流就分别排队执行。其中李四、王五都是张三叫来的,所以张三⼀般被称为主线程(Main Thread)。

为什么要有线程

首先, "并发编程" 成为 "刚需"

• 单核 CPU 的发展遇到了瓶颈. 要想提高算力, 就需要多核 CPU.而并发编程能更充分利用多核 CPU 资源.

• 有些任务场景需要 "等待 IO", 为了让等待 IO 的时间能够去做⼀些其他的⼯作, 也需要用到并发编程.

其次, 虽然多进程也能实现并发编程,,但是进程的频繁的申请和释放会带来资源的额外开销,线程比进程更轻量。

• 创建线程比创建进程更快.

• 销毁线程比销毁进程更快.

• 调度线程比调度进程更快.

最后, 线程虽然比进程轻量, 但是⼈们还不满足, 于是又有了 "线程池"(ThreadPool) 和 "协程" (Coroutine)

进程和线程的关系与区别

1. 进程是包含线程的. 每个进程至少有一个线程存在,即主线程。

2. 进程和进程之间不共享内存空间. 同一个进程的线程之间共享同一个内存空间

3. 进程是系统分配资源的最小单位,线程是系统调度的最小单位

4. 每个线程也是独立的执行流,可以执行一些代码,并单独参与到CPU调度中(状态,上下文,优先级,记账信息)每个线程都有一份

5. 每个进程,有自己的资源,进程中的线程共用这一份资源(内存空间和文件描述符表)

6. 进程与进程之间不会相互影响, 但是一个线程挂了, 可能把同进程内的其他线程⼀起带走(整         个进程崩溃).

7. 同一个进程的线程之间,可能会相互干扰,引起线程安全问题

8. 线程不是越多越好,线程过多会加大调度开销

Java 的线程 和 操作系统线程 的关系

线程是操作系统中的概念,操作系统内核实现了线程这样的机制,并且对用户层提供了一些API供用户使用(如 Linux 的 pthread 库)

Java标准库中Thread类可以视为是对操作系统提供 api 进行了进一步的抽象与封装。

创建线程的方法

方法1 继承 Thread 类

1.继承Thread来创建一个线程类

class MyThread extends Thread {
      @Override
      public void run() {
             System.out.println("这⾥是线程运⾏的代码");
 }
}

2.创建 MyThread 类的实例

MyThread t = new MyThread();

3.调用start 方法启动线程

t.start(); // 线程开始运⾏

方法2 实现Runnable接口

1.实现Runnable接口

class MyRunnable implements Runnable {
     @Override
     public void run() {
         System.out.println("这⾥是线程运⾏的代码");
 }
}

2.创建Thread类实例,调用Thread的构造方法时将Runnable对象作为target参数.

Thread t = new Thread(new MyRunnable());

3.调用start方法

t.start(); // 线程开始运⾏

对比上面两种方法:

1.继承Thread类,直接使用this就可以表示当前线程对象的引用.

2.实现Runnable接口,this表示的是MyRunnable的引用.需要使用Thread.currentThread()

方法3 匿名内部类创建 Thread 子类对象

// 使⽤匿名类创建 Thread ⼦类对象
Thread t1 = new Thread() {
     @Override
     public void run() {
         System.out.println("使⽤匿名类创建 Thread ⼦类对象");
 }
};

方法4 匿名内部类创建 Runnable 子类对象

// 使⽤匿名类创建 Runnable ⼦类对象
Thread t2 = new Thread(new Runnable() {
     @Override
     public void run() {
         System.out.println("使⽤匿名类创建 Runnable ⼦类对象");
 }
});

方法5 lambda 表达式创建 Runnable 子类对象(常用)

// 使⽤ lambda 表达式创建 Runnable ⼦类对象
Thread t3 = new Thread(() -> System.out.println("使⽤匿名类创建 Thread ⼦类对象"));
Thread t4 = new Thread(() -> {
 System.out.println("使⽤匿名类创建 Thread ⼦类对象");
});

总结

以上是对线程的简单认识及进程与线程的一些关系与区别

进一步认识进程可查看进程是什么?-CSDN博客

谢谢

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值