Java------线程基础讲解

本文详细解析了多任务的概念,包括并发和并行的区别,以及如何利用多线程实现多个函数同时执行。重点介绍了Java线程生命周期和创建方式,通过实例演示了继承Thread类和实现Runnable接口创建线程的方法。
摘要由CSDN通过智能技术生成

线程

线程简介

任务

多任务是指在同一时间内执行多个任务,任务的执行方式并发并行两种方式,使用多任务就能充分利用CPU资源提高程序的执行效率,让程序具备处理多个任务的能力。

1.多任务是什么?

多任务是指在同一时间内执行多个任务,例如:你一边运行QQ,一边打开QQ音乐听歌曲,一边使用Word做着文档。这就是多任务

2.多任务执行方式

并发和并行

并发:CPU核心数小于任务数,CPU轮流(交叉)执行多个任务

并行:CPU核心数大于等于任务数,每个CPU核心都可以单独执行一个任务

3.利用现学知识能够让两个函数或者方法同时执行吗?

不能,因为之前所写的程序都是单任务的,也就是说一个函数或者方法的执行完成另外一个函数或者方法才能执行,要实现这种操作就需要使用多任务。多任务的最大好处就是充放利用CPU资源提高程序的执行效率。

使用多任务就能充分利用CPU资源提高程序的执行效率,让你的程序具备处理多个任务的能力。多任务执行方式有两种:并发和并行,但并行才是多个任务真正意义一起执行。

多线程

我们知道,进程是运转的程序,就是为了在CPU上实现多道编程而发明的一个概念,但是进程在一个时间只能干一件事。如果想同时干两件事,例如同时看两场电影,我们自然就想到了分身术,就像孙悟空那样同时变出多个真身。

当然人在现实中进行分身显然是办不到的,但进程却可以办到,办法就是线程。线程就是我们为了让一个进程能够同时干多件事情而发明的“分身术”。

既然线程是进程的分身,每个线程自然在本质上是一样的,即拥有同样的程序文本。但由于是分身,自然也应该有不一样的地方,这就是线程执行时的上下文不一致。 事实上,我们说线程是进程里面的一个执行上下文,或者执行序列。显然,一个进程可以同时拥有多个执行序列。这就像舞台,舞台上可以有多个演员同时出场,而这些演员和舞台就构成了一出戏。类比进程和线程,每个演员是一个线程,舞台是地址空间,这个同一个地址空间里面的所有线程就构成了进程。在线程模式下,一个进程至少有一个线程,但也可以有多个线程。
1.在操作程序中进程和线程的区别:

进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1–n个线程(进程是资源分配的最小单位)

线程:同一类线程共享代码和数据空间,每个线程都有独立的运行栈和程序计数器(PC),线程切换开销小。(线程是CPU调度的最小单位)

多进程:是指操作系统同时运行多个任务(程序)

多线程:是指在同一程序中有多个顺序流在执行。

例子:当你打开王者荣耀,进行一局游戏时,进程可以比作你开的这把游戏 ,线程比作每个玩家所选的英雄或者游戏中的水晶野怪等。

核心概念

  • 线程就是独立的执行路径
  • 在程序运行时,即使没有自己创建线程,后台也会有多个线程,如主线程,gc线程
  • main()称之为主线程,为系统的入口,用于执行整个程序
  • 在一个进程中,如果开辟了多个线程,线程的运行由调度器安排调度,调度器是与操作系统紧密相关的,先后顺序是不能人为的干预的
  • 对同一份资源操作时,会存在资源抢夺的问题,需要加入并发控制
  • 每个线程在自己的工作内存交互,内存控制不当会造成数据不一致。(例如:10000个人抢100张票)

补充:

Java的线程生命周期:New(初始化状态)、Runnable(可运行/运行状态)、Blocked(阻塞状态)、Waiting(无时间限制的等待状态)、Timed_Waiting(有时间限制的等待状态)、Terminated(终止状态)

其中阻塞又分为三种情况:
1.等待阻塞:运行的线程执行wait方法,则该线程会释放占用的的所有资源,jvm会把该线程放入==“等待池”==中,进入这个状态后是不能被自动唤醒的,需要调用notify/notifyAll 方法才能被唤醒。

2.同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被其它线程占用,则jvm会把该线程放入==“锁池”==中。

3.其它阻塞:运行的线程执行sleep/join方法、或者发出了I/O请求时,jvm会把该线程置为阻塞状态。当sleep方法等待超时、join方法等待线程终止或者超时、I/O处理完毕时,线程将重新转入就绪状态。

线程五种状态的具体形况:
1.新建状态(New):新创建了一个线程对象,该线程的生命周期开始。
2.就绪状态(Runnable):线程对象创建后,其它线程调用了该对象的start方法,该状态的线程会位于可运行的线程池中,变得可运行,等待cpu的使用权。
3.运行状态(Running):就绪状态的线程获取到了cpu的时间片,执行程序代码。
4.阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃cpu的使用权,暂停或停止运行,直到线程进入就绪状态,才有机会获得cpu的青睐从而转入运行状态。
5.死亡状态(Dead):线程执行完了或者因为异常而退出的run方法,该线程生命周期结束。

三种创建方式

  • Thread class-----》继承Thread类(重点)
  • Runnable接口-----》实现Runnable接口(重点)
  • Callable接口-----》实现Callable接口(目前了解)

实现Thread

  • 自定义线程类继承Thread类
  • 重写run()方法,编写线程执行主体
  • 创建线程对象,调用start()方法启动线程

代码样式:

//创建线程方式一:继承Thread类,重写run()方法,调用start开启线程
//总结:注意,线程开启不一定立即执行,由CPU调度执行
public class TestThread  extends Thread{
//    重写快捷键ctrl+o
    @Override
    public void run() {
        //run方法线程体
        for (int i = 0; i < 20; i++) {
            System.out.println("我在看代码------"+i);
        }
    }

    public static void main(String[] args) {
        //main线程,主线程

//        创建一个线程对象
        TestThread testThread = new TestThread();
//        调用start()方法开启线程
        testThread.start();

        for (int i = 0; i < 20; i++) {
            System.out.println("我在学习多线程------"+i);
        }
    }
}

效果图(部分):

我在看代码------0
我在学习多线程------0
我在看代码------1
我在学习多线程------1
我在看代码------2
我在学习多线程------2
我在看代码------3
我在学习多线程------3

实现Runnable

  • 定义MyRunnable类实现Runnable接口
  • 实现run()方法,编写线程执行体
  • 创建线程对象,调用start()方法启动线程

代码样式:

//创建线程方式二:实现runnable接口,重写run方法,执行线程需要丢入runnable接口实现类,调用start方法
public class MyRunnable implements Runnable {
    @Override
    public void run() {
        //run方法线程体
        for (int i = 0; i < 20; i++) {
            System.out.println("我在看代码------"+i);
        }
    }

    public static void main(String[] args) {
        //创建runable接口的实现类对象
        MyRunnable runnable = new MyRunnable();
//       创建线程对象,通过线程对象来开启我们的线程,代理
        Thread thread = new Thread(runnable);
        thread.start();
//              或(上下两种都可行)
//        new Thread(runnable).start();

        for (int i = 0; i < 20; i++) {
            System.out.println("我在学习多线程------"+i);
        }
    }
}

效果图(部分):

我在看代码------0
我在学习多线程------0
我在看代码------1
我在学习多线程------1
我在学习多线程------2
我在看代码------2
我在学习多线程------3
我在学习多线程------4

小结

  • 继承Thread类

    • 子类继承Thread类具备多线程能力

    • 启动线程:子类对象.sart()

      不建议使用:避免OOP单继承局限性

  • 实现Runnable接口

    • 实现接口Runnable具有多线程能力

    • 启动线程:传入目标对象+Thread对象.start()

      推荐使用:避免单继承局限性,灵活方便,方便同一个对象被多线程使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值