《03-javaEE系列---线程》

目录

前言

1.线程是什么

2.为什么要有线程?

3.进程和线程的区别

4.操作系统也有线程,和java的线程有什么关系呢?

引言

编写第一个多线程程序

java中创建线程的写法其实有很多种

一.继承Thread重写run

二.实现Runable接口

三.使用匿名内部类,继承Thread

四.使用匿名内部类,实现Runable

五.使用Lambda表达式(最推荐)


前言

1.线程是什么

一个线程就是一个执行流(指的就是程序中的指令是按照什么顺序被执行的。你可以把它想象成做事情的流程图)。每个线程之间都可以按照顺序执行自己的代码,多个线程之间“同时”执行着多份代码。

举个日常生活中的例子:

想象你家里人(妈妈)做晚饭。比如:

  1. 洗菜
  2. 切菜
  3. 炒菜
  4. 煮饭
  5. 摆盘

只能一件事情做完,再做下一件。执行流是线性的。就像单线程程序。


于是妈妈请了家里人(你和你弟弟)一起来帮忙:

  • 妈妈在切菜(线程A)
  • 你在洗菜(线程B)
  • 弟弟在煮饭 (线程C)

大家同时进行,每个人都有自己的执行流,但是大家都最终完成了一个目标:做晚饭。这就像程序中不同线程协同完成任务。

于是我们把上述情况称为多线程,将一个大任务分解成不同的小任务,交给不同的执行流来执行。其中,你和你弟弟都是被叫来的,所以妈妈一般被称为主线程,主线程最开始独立负责所有工作。

2.为什么要有线程?

  • 首先,“并发编程”是“刚需”
  1. 单核CPU的性能已经到了瓶颈,要想提高算力,就需要多核CPU,而并发编程能够更充分利用多核CPU资源。
  2. 有些任务厂家需要等待IO,为了让这个等待时间能够去做一些其他的工作,也需要用到并发编程。
  • 其次,线程就是比进程更轻量
  1. 创建线程比创建进程更快
  2. 销毁线程比销毁进程更快
  3. 调度线程比调度进程更快

虽然线程比进程更轻量,但是线程创建多了也需要考虑到性能,于是又有了“线程池(ThreadPool)”和“协程(Coroutine)”

3.进程和线程的区别

  • 进程是包含线程的,每个进程至少有一个线程存在(即主线程)
  • 进程和进程之间不共享内存空间,同一个进程的线程之间共享同一份内存空间

比如之前讲到的例子:

概念做饭比喻
进程整个厨房,有独立空间
主线程妈妈,第一个且必须存在的(不然大家都别吃晚饭了)
多线程妈妈+你+弟弟同时在厨房工作
线程共享所有人都能直接使用厨房里的食材、厨具(共享内存)
进程隔离邻居家的厨房是完全独立的,不能直接拿对方的食材或厨具(进程间内存隔离)
进程间通信如果真要借食材或厨具,需要走到对方家门口敲门请求(IPC)

整个厨房就像一个进程,厨房有自己独立的空间(内存空间),和其他厨房(其他进程)是隔离的,比如邻居家的厨房和你家的厨房不共享食材和厨具

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

4.操作系统也有线程,和java的线程有什么关系呢?

java标准库中的线程(Thread)可以视为是对操作系统提供的API进行了进一步抽象和封装.

引言

编写第一个多线程程序

实例代码


class MyThread extends Thread {

    @Override
    public void run() {
        while (true) {
            System.out.println("hello thread");
        }
    }
}


public class ThreadDemo {
    public static void main(String[] args) {
        MyThread thread=new MyThread();
        thread.start();
        while (true) {
            System.out.println("hello main");
        }
    }
}

使用.start()创建并启动线程,而不是直接调用run()

输出结果


代码分析


为什么我上述结果看起来像顺序执行而不是交错执行呢?

可能的原因有几个,常见的是:

  • 主线程执行得太快了 —— 新开出来的线程还没来得及抢到 CPU 资源,主线程就已经输出完了。

  • 子线程启动有延迟 —— 调用 start() 后,线程不是立刻运行,而是由操作系统调度,调度本身需要一点时间。

  • 缺少等待子线程结束的操作 —— 如果主线程执行完直接退出,子线程就可能被强制终止,或者被 "孤立"。

通常,为了在学习多线程时观察更明显的"并发交错",可以做两件事:

  • 在循环里加一点点延迟,比如 Thread.sleep(10);

  • 在主线程里等待子线程结束,比如用 join() 方法。

为什么看上去每次都是"hello main"先执行?

线程的创建也是有成本的,只不过和进程相比开销比较小,但不是没有


改进

上述代码我们希望它执行得慢一点,因此可以使用线程中提供的sleep方法

由于可能会被提前唤醒(报错),因此我们加入try-catch

改进后的run方法

 可以试着自己写一遍,然后查看运行结果


 

java中创建线程的写法其实有很多种

一.继承Thread重写run

1.继承Thread 

2.重写run


二.实现Runable接口

1.继承Runable接口

2.重写run方法


三.使用匿名内部类,继承Thread


四.使用匿名内部类,实现Runable


五.使用Lambda表达式(最推荐)

其中Lambda就是一个匿名函数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值