Java 多线程简单理解

 学习内容摘自“菜鸟教程”、举铁小白、B站“遇见狂神说


线程、进程、程序

  • 进程:一个进程包括由操作系统分配的内存空间,包含一个或多个线程
  • 线程:不能独立的存在,它必须是进程的一部分
  • 一条线程指的是进程中一个单一顺序的指令流------就是你想用它干啥子
  • 一个进程中可以并发多个线程,每条线程并行执行不同的任务------就是你做爷爷发号施令,一群孙子帮你干活
  • 程序:程序是指令+数据的有序集合,进程是程序的一次执行
  • 程序是死的(静态),进程是活的程序(动态)
  • 程序一般来说是永存的,进程是有时限的

并行与并发

  • 串行:单核cpu运行多线程时,时间片进行很快的切换。线程轮流执行cpu
  • 并行:多核cpu运行 多线程时,真正的在同时运行,同一时间动手做(doing)多件事情的能力
  • 并发:同一时间应对(dealing with)多件事情的能力
  • 微观串行,宏观并行
  • 线程数多于核心数 仍是并行+串行的方式运行程序

多线程的必要性

  • 提高程序的利用率------实现更多功能,就像你一边蹲坑一边刷抖音,脑子里还在想啥事情
  • 合理分配CPU资源------省得你家的毛孩子抢电视抢玩具(你先去玩玩具,你先去睡觉,还有你去......)

多线程可能存在的缺点

  • 初始化启动更慢
  • 资源开销大、快
  • 编码复杂性可能更高------线程的同步啊,加锁啊
  • 线程与线程之间可能存在相互影响------一个线程的崩溃会不会引发另一个线程的问题
  • 安全性问题?

一个线程的生命周期


请添加图片描述

  • 继承Thread类

  1. 自定义线程类继承Thread类

  2. 重写run()方法,编写线程执行体

  3. 创建线程对象,调用start()方法启动线程
//创建线程方式一:
//1.继承Thread类---为了能让他干啥子,
//2.重写run()方法---你想让它干啥子,
//3.调用start开启线程---开始干啥子。

public class TestThread1 extends Thread{
    @Override
    public void run(){
        for (int i = 0; i < 6; i++) {
            System.out.println("我要学java发大财!--"+i);
        }
    }
    public static void main(String[] args) {
        //main线程,主线程
        //创建一个线程对象
        TestThread1 testThread1 = new TestThread1();
        //调用start()方法开启线程
        testThread1.start();
        for (int i = 0; i < 66; i++) {
            System.out.println("我在学习线程发大财--"+i);
        }
    }
}
  • 实现Runnable

  1. 定义一个类实现Runnable接口

  2. 实现run()方法,编写线程执行体

  3. 创建线程对象,调用start()方法启动线程
//创建线程方式2:
// 实现runnble接口,
// 重写run()方法,执行线程需要丢入runnable接口类,
// 调用start()方法
public class TestThread2 implements Runnable{
    @Override
    public void run(){
        for (int i = 0; i < 6; i++) {
            System.out.println("我在学java赚大钱--"+i);
        }
    }
    public static void main(String[] args) {
        //创建runnbale接口的实现类对象
        TestThread2 testThread2 = new TestThread2();
        //创建线程对象,通过线程对象来开启线程代理
        new Thread(testThread2).start();
        for (int j = 0; j < 66; j++) {
            System.out.println("我在学习线程赚大钱--"+j);
        }
    }
}
  • 通过 Callable 和 Future 创建线程

      1. 创建 Callable 接口的实现类,并实现 call() 方法,该 call() 方法将作为线程执行体,并且有返回值。

      2. 创建 Callable 实现类的实例,使用 FutureTask 类来包装 Callable 对象,该 FutureTask 对象封装了该 Callable 对象的 call() 方法的返回值。

      3. 使用 FutureTask 对象作为 Thread 对象的 target 创建并启动新线程。

      4. 调用 FutureTask 对象的 get() 方法来获得子线程执行结束后的返回值。

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class TestThread3 implements Callable<Integer> {

    //实现callable的call方法
    @Override
    public Integer call() throws Exception {
        int i = 0;
        for (; i < 6; i++) {
            System.out.println("我在学java赚大钱--"+i);
        }
        //有返回值哦
        return i;
    }

    public static void main(String[] args) {

        TestThread3 thread3 = new TestThread3();
        //使用 FutureTask 对象作为 Thread 对象的 target 创建并启动新线程。
        FutureTask<Integer> ft = new FutureTask<>(thread3);
        //创建线程对象,通过线程对象来开启线程代理
        new Thread(ft).start();

        for (int j = 0; j < 66; j++) {
            System.out.println("我在学习线程赚大钱--"+j);
        }
        try {
            System.out.println("子线程-Call方法的返回值:" + ft.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

以上三种方式都可以实现相似的效果。


小结

推荐使用实现Runnable接口这种方式——原因:

相比继承 Thread 类:
    1)避免 Java 的单继承(你一个类只能继承一次不是吗)特性带来的局限
    2)增强程序的健壮性,代码能够被多个线程共享,代码与数据是独立的
    3)线程池只能放入实现 Runable 或 Callable 类线程,不能直接放入继承 Thread 的类
相比实现 Callable 接口:
    1)Runnable 是自从 java1.1 就有了,而 Callable 是 1.5 之后才加上去的
    2)Callable 接口支持返回执行结果,此时需要调用 FutureTask.get()方法实现,此方法会阻塞主线程直到获取返回结果,当不调用此方法时,主线程不会阻塞

(我也没搞太懂,先做记录,慢慢理解吧!)

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

骄傲的苦茶籽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值