Java十分钟入门多线程上篇

什么是多线程?

在学习前,我们先对程序、进程、线程、并行、并发有个基础的概念了解:

  • 程序: 为完成指定任务,用编程语言编写的一组指令的集合,即指一段静态的代码,静态对象。
  • 进程: 是程序的一次执行过程,是一个动态的过程,进程自身有产生、使用和消亡的过程。(也称为生命周期,在后面会介绍)
  • 线程: 进程可进一步细化为线程,是一个程序内部的一条执行路径,也就是进程内有线程
  • 并行: 指两个或者多个事件在同一时刻发生,(同时发生)
  • 并发: 指两个或者多个事件在同一个时段内发生,(并不是同时发生)

更好的理解进程和线程:

打开计算机任务管理器:

多线程有什么用?

我们就不看其他长篇大论,简单的说就是:节省时间,提高效率(在CPU满足的情况下同时执行多个任务)

举个例子:

12306大家肯定很熟悉,在高峰期的时候,会有几十万的用户同时在浏览和购票,假如你是第1000个进入购票系统的,系统不会让你等待前面999人买完你才可以买,不管你什么时候加入购票系统,随时都可以买,这就是多线程。而且CPU的运算速度让你感觉不用等待延迟(在CPU处理负载能力之内)。

多线程优点小结:

  • 提高了用户的体验度,使程序的相应速度更快
  • 占用大量的处理时间的任务可以使用多线程来提高CPU的使用效率
  • 可以设优先级来优化性能

线程的生命周期:

线程的生命周期包括5个阶段: 新建、就绪、运行、阻塞、销毁

  • 新建:在编译期间创建线程对象就属于新建状态,如Thread t1=new Thred()。(在下面介绍如何创建)
  • 就绪: 当一个线程对象调用了start()方法就属于就绪状态,这时候线程处于等待CPU执行此线程的任务, 谁先抢到cpu资源就谁先执行,是随机的。
  • 运行: 就绪状态的线程获得CPU资源执行的任务的时候就是运行状态,run()方法用于执行线程操作
  • 阻塞状态:在运行状态的时候,可能因为某些原因导致运行状态的线程变成了阻塞状态不能再继续执行任务, 这个时候其他线程获取CPU资源的可能性就更大了,CPU并不会等待阻塞状态的线程(任务)而去执行其他线程 的任务,也可以通过线程调度的机制“线程休眠”让运行状态下的线程任务变成阻塞,或者让阻塞状态的线 程“唤醒”变成就绪状态。直到再次等待CPU分配资源进入到运行状态。
  • 销毁:如果线程正常执行完任务后或者线程被提前强制终止或者是因为出现异常导致线程任务 结束,都属于销毁状态。

关于阻塞状态的进一步理解:

假如你去超市买东西(创建),选完东西准备结账(就绪),你在付款了,但是的时候发现钱不够了(运行),不能完成支付,需要打电话给朋友借一点,因为你没有办法支付了(这就进入的阻塞状态),就不能进入下一步骤(走出超市,对应销毁)。

注意: 进入阻塞状态后并不是说不管你了,而是准备好后再次让CPU来处理你。就是你借到钱了,收银员会再次让你去付款。

创建多线程:

主线程:

当Java程序启动的时候,一个线程立刻执行,该线程叫做主线程(main Thread),因为他是程序开始就执行的。

主线程的作用:

  • 产生其他子线程的线程
  • 必须完成最后的执行,因为它还需要执行各种关闭动作

实现多线程有5种方式:

  • 继承Thread父类重写run()方法,Java是单继承如果继承了Thread其他父类就不能再继承。(这种方式不建议)
  • 实现Runable接口重写run()方法。(最常用)
  • 实现Callable接口,调用有返回值的call方法
  • 线程池创建多线程
  • 通过Java8新特性Lambda表达式实现多线程

主线程:

public class test {
    public static void main(String[] args) {
        //获取当前线程的对象
        Thread t = Thread.currentThread();
        //输出当前线程的名字:
        System.out.println(t.getName());
        t.setName("我是主线程");
        System.out.println(t.getName());
    }
}

//输出:
//main
//我是主线程

通过上面的代码可以知道当前主线程的名字,也可以修改线程名、 关于Thread的方法介绍参考官方文档:

https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Thread.html

1、继承Thread父类重写run()方法创建多线程:

继承Thread重写run方法:

//创建一个以main为主线程的子线程
public class MyThread extends Thread{
    @Override
    public void run(){
        for (int i = 1; i < 6; i++) {
            System.out.println("我是子线程:"+i);
        }
    }
}

测试类:

public class test {
    public static void main(String[] args) {

        //创建子线程对象(新建状态)
        MyThread t = new MyThread();
        //就绪状态,等待CPU执行该线程任务
        t.start();
        for (int i = 1; i < 6; i++) {
            System.out.println("main任务:主线程执行:"+i);
        }
    }
}

结果:

2、实现Runable接口重写run()方法(最常用)

创建子线程:

public class MyThread implements Runnable{

    @Override
    public void run(){
        for (int i = 1; i < 10; i++) {
            System.out.println("子线程-"+Thread.currentThread().getName()+i);
        }
    }
}

测试类:

public class test {
    public static void main(String[] args) {

        //创建子线程对象(新建状态)
        MyThread t1 = new MyThread();
        t1.setName("我是A线程:");
        MyThread t2 = new MyThread();
        t2.setName("我是B线程:");
        MyThread t3 = new MyThread();
        t3.setName("我是C线程:");

        //就绪状态,等待CPU执行该线程任务
        t1.start();
        t2.start();
        t3.start();
    }
}

结果:

3、实现Callable<?>接口实现有返回值的多线程

public class MyThread implements Callable<Boolean> {

    @Override
    public Boolean call() throws Exception {
        try{
            //因为是泛型接口,call实 现了线程任务,并且返回值可以自定义
            System.out.println("实现了Callable接口重写call方法");
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
}

测试类:

public class test {
    public static void main(String[] args) throws ExecutionException, InterruptedException {

        //创建对象:
        MyThread myThread = new MyThread();
        //通过线程池帮你创建了2个线程对象
        //ExecutorService是Java中对线程池定义的一个接口,它java.util.concurrent包中
        ExecutorService service = Executors.newFixedThreadPool(2);
        //通过线程池对象调用submit方法,提交执行call方法的线程任务,最后返回结果
        Future<Boolean> result1 = service.submit(myThread);
        Future<Boolean> result2 = service.submit(myThread);

        boolean r1= result1.get();
        boolean r2= result2.get();

输出:

实现了Callable接口重写call方法
实现了Callable接口重写call方法
我是子线程1,返回的结果:true
我是子线程2,返回的结果:true

其他两个创建多线程的方式不怎么用,就不一一介绍,大家也可以看看其他技术博客学习~~

小结:

这篇文章主要将了多线程的概念以及创建多线程的方式,多线程还有很多的内容,就在下一篇再继续介绍啦!感谢阅读!

到此这篇关于Java十分钟入门多线程上篇的文章就介绍到这了,更多相关Java 多线程内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 高价值Java多线程面试题分析

    问题一 A线程正在执行一个对象中的同步方法,B线程是否可以同时执行同一个对象中的非同步方法? 可以,两个线程运行所需资源不同,不需要抢占. 案例一. package duoxiancheng2; /** * @author yeqv * @program A2 * @Classname Ms1 * @Date 2022/2/7 19:08 * @Email w16638771062@163.com */ public class Ms1 { //A线程正在执行一个对象中的同步方法,B线程是否可以

  • 一篇文章带你Java多线程入门

    目录 多线程的四种创建方式 1.继承Thread类 2.实现Runnable接口 3.实现Callable接口 4.使用线程池 线程的优先级 测试Thread中常用的方法 线程的生命周期 多线程的同步控制 1.同步代码块 2.同步方法 3.同步锁 线程通信 wait/notify模式 sleep和wait的异同 总结 多线程的四种创建方式 1.继承Thread类 /* * 多线程的创建,方式一:继承Thread类 * 1.创建一个继承于Thread类的子类 * 2,重写Thread类的run()

  • 聊聊java多线程创建方式及线程安全问题

    什么是线程 线程被称为轻量级进程,是程序执行的最小单位,它是指在程序执行过程中,能够执行代码的一个执行单位.每个程序程序都至少有一个线程,也即是程序本身. 线程的状态 新建(New):创建后尚未启动的线程处于这种状态 运行(Runable):Runable包括了操作系统线程状态的Running和Ready,也就是处于此状态的线程有可能正在执行,也有可能正在等待着CPU为它分配执行时间. 等待(Wating):处于这种状态的线程不会被分配CPU执行时间.等待状态又分为无限期等待和有限期等待,处于无

  • Java多线程之线程安全问题详解

    目录 1.什么是线程安全和线程不安全? 2.自增运算为什么不是线程安全的? 3.临界区资源和竞态条件 总结: 面试题: 什么是线程安全和线程不安全? 自增运算是不是线程安全的?如何保证多线程下 i++ 结果正确? 1. 什么是线程安全和线程不安全? 什么是线程安全呢?当多个线程并发访问某个Java对象时,无论系统如何调度这些线程,也无论这些线程将如何交替操作,这个对象都能表现出一致的.正确的行为,那么对这个对象的操作是线程安全的. 如果这个对象表现出不一致的.错误的行为,那么对这个对象的操作不是

  • Java十分钟入门多线程上篇

    什么是多线程? 在学习前,我们先对程序.进程.线程.并行.并发有个基础的概念了解: 程序: 为完成指定任务,用编程语言编写的一组指令的集合,即指一段静态的代码,静态对象. 进程: 是程序的一次执行过程,是一个动态的过程,进程自身有产生.使用和消亡的过程.(也称为生命周期,在后面会介绍) 线程: 进程可进一步细化为线程,是一个程序内部的一条执行路径,也就是进程内有线程 并行: 指两个或者多个事件在同一时刻发生,(同时发生) 并发: 指两个或者多个事件在同一个时段内发生,(并不是同时发生) 更好的理

  • Java十分钟入门多线程下篇

    目录 1.线程池: 2.创建线程池: 1.newCacheThreadPool: 2.newSingleThreadExecutor: 3.newFixedThreadPool(inta): 4.newScheduledTreadPool: 3.线程池创建自定义线程: 4.Runnable和Callable的区别: 5.线程池总结: 1.线程池: 什么是线程池? 咱们也不看长篇大论,通俗的来讲,线程池就是装线程的容器,当需要用的时候去池里面取出来,不用的时候放回去或者销毁.这样一个线程就可以反复

  • Java十分钟入门多线程中篇

    目录 1.线程的调度: 1.设置优先级(Priority): 2.休眠(sleep) 3.强制运行(join) 4.礼让(yield) 2.定时器线程: 3.线程的同步: 举例说明: 我们知道飞机在天上飞行是有固定的航线(可以理解成线程),每个机场都有最大的运行负载能力,当运行情况超过了负载能力的时候,这就需要塔台调度参与,会根据每架飞机的优先级排序.当在航线的时候,如果出现紧急情况,会让其他飞机避让,让这架飞机优先级提高,先降落.这就是调度,计算机程序线程运行也是这样的. 1.线程的调度: 在

  • Java十分钟精通集合的使用与原理上篇

    目录 什么是集合? 集合分为Collection和Map两种体系 一.Collection接口: 二.Map接口下分为HashMap和TreeMap: 集合总结: Collections工具类: 什么是集合? 比如我们去买超市买很多东西,我们不可能拿一样就去收银台,我们可能是先放到购物车内,然后再统一处理,所以购物车相当于一个容器,可以装很多东西,在Java中的集合也是相当于一个容器,可以装很多数据. 集合继承关系图: 但是这张图太复杂了,我们看一张简便的: 集合分为Collection和Map

  • 十分钟上手正则表达式 上篇

    目录 一.正则表达式的定义: 二.正则表达式的类型 三.定义 BRE 模式 3.1 纯文本 3.2 特殊字符 3.3 锚字符 3.3.1 锁定在行首 3.3.2 锁定在行尾 3.3.3 组合锚点 3.4 点号字符 3.5 字符组 3.6 排除型字符组 3.7 区间 3.8 特殊的字符组 3.9 星号[*] 一.正则表达式的定义: 正则表达式是你所定义的 模式模板 ( pattern template ), Linux 工具可以用它来过滤文本. Linux工具(比如sed 编辑器或 gawk 程序

  • Java十分钟精通String类的各种使用方法

    String String类: 代表字符串,提供了开发中常用的字符串处理的方法,如:求字符串的长度.截取字符串.替换字符串等方法,符串是常量,它的值创建之后就不可以再修改了. 首先我们先查一下官方文档,看看官方给String类定了什么方法: String也是属于java.lang包,所以不需要导入,这里就部分展示,全部的内容可以参考: https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.htm

  • Java十分钟精通Lambda表达式

    目录 1.简介 2.Lambda表达式的使用: 1.在普通方法内的使用 2.带参方法的使用 3.Lambda表达式实现多线程 4.Lambda表达式操作运算 5.Lambda表达式方法引用 6.Lambda表达式对集合的使用 3.总结 1.简介 首先Lambda表达式是属于Java8的 一个新特性,提供Java编程中对于函数式编程的支持,有助于代码的简洁,可以取代大半部分的匿名函数,尤其对于集合的遍历和集合的操作,极大的简化了代码. Lambda表达式的主体: 函数式接口: 注意: Lambda

  • Java十分钟精通多态与抽象类的使用与原理

    我们知道Java的三大特性:封装.继承.多态.前两个之前在Java入门(六)已经讲到,现在来讲多态这个特性. 什么是多态? 多态顾名思义即为多种形态的意思 Java中多态的含义: 发送消息给某个对象,让这个对象自行决定采用哪种行为响应这个消息 子类对象的引用赋值给父类引用变量来实现动态的方法调用 Java中形成多态的前提: 继承 父类方法的重写 向上转型 我对多态的解释: 比如我们,是人,也是学生,也是年轻人,我可以用人的身份去做事情,也可以用学生的身份去买学生票,也可以用年轻人的身份做公益,这

  • Java十分钟快速掌握单例模式

    目录 前言 1.什么是单例模式: 2.单例模式的优缺点: 3.懒汉模式(比较常用) 4.饿汉模式[推荐使用] 5.单例模式的应用场景 6.单例模式的应用实例 小结: 前言 首先在Java中有23种设计模式: 创建型模式: 工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式结构型模式: 适配器模式.装饰者模式.代理模式.外观模式.桥接模式.组合模式.享元模式行为型模式::策略模式.模板方法模式.观察者模式.迭代子模式.责任链模式.命令模式.备忘录模式.状态模式.访问者模式.中介者模式.解释

  • Spring Security十分钟入门教程

    目录 写在前面 目标 开始 不引入Spring Security访问接口 引入Spring Security访问接口 退出登录 后记 写在前面 我们在学习技术的过程中,学习的渠道大概有以下几种:看书,视频,博客.我们会发现,一种技术开始流行的时候,各种形式的讲述也就出现了.那么,出书,录视频,写博客的人,在他们之前,是没有什么现成的东西让他们学习的,他们是怎么上手的呢?换句话说,怎么才能有效的快速的上手一门技术呢? 这篇文章,我们一起从零开始学习SpringSecurity,技术点不重要,重要的

随机推荐