P2 线程创建——多线程详解(B站狂神说)

本文详细介绍了Java中的多线程概念,包括线程创建的三种方式(继承Thread类、实现Runnable接口、实现Callable接口),并发问题的示例(买火车票、龟兔赛跑),以及静态代理和Lambda表达式的应用。通过实例代码演示了线程的启动、状态以及同步通信,适合Java初学者深入理解多线程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

多线程秋招真的很常问,自己看B站视频笼统的过了一遍复习。
这个老师讲的想对比较适合初学,高阶建议啃书。😀
记了一些笔记写成博客分享出来。📕

在这推荐up主:狂神说。👍
指路b站视频链接:

https://www.bilibili.com/video/BV1V4411p7EF/


多线程 Java.Thread

P1  线程简介
P2  线程创建
    初识并发
    静态代理+lambda表达式

P3  线程状态
P4  线程同步
P5  线程通信问题
P6  线程池


P2 线程创建

  

   初识并发

  

   静态代理+lambda表达式

  
  

1.线程创建

Thread、Runnable、Callable

线程开启不一定立即执行,由CPU调度执行。
不一定按start()顺序执行。

  
  
①继承Thread类(Thread实现了Runnable接口)

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

子类继承Thread类具备多线程能力
启动线程:子类对象.start()
不建议使用:避免OOP单继承局限性

//创建线程方式1:
//      继承Thread类,
//      重写run()方法,
//      调用start开启线程
public class TestThread1 extends Thread{

    @Override
    public void run() {
        //run方法线程体
        for (int i = 0; i < 20; i++) {
            System.out.println("在学习多线程"+i);
        }
    }

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

        //创建线程对象
        TestThread1 testThread1=new TestThread1();
        //调用start()方法开启线程
        testThread1.start();

        for (int i = 0; i < 20; i++) {
            System.out.println("在看主线程啊啊啊啊啊"+i);
        }
    }
}

  
  
②实现Runnable接口

  step1:定义MyRunnable类实现Runnable接口
  step2:重写run()方法,编写线程执行体
  step3:创建线程对象,丢入runnable接口实现类(代理),调用start()方法启动线程

实现接口Runnable具有多线程能力
启动线程:传入目标对象+Thread对象.start()
推荐使用:避免单继承局限性,灵活方便,方便同一个对象被多个线程使用

//创建线程方式2:
//      实现runnable接口
//      重写run方法
//      执行线程需要丢入runnable接口实现类,调用start
public class TestThread2 implements Runnable{

    @Override
    public void run() {
        //run方法线程体
        for (int i = 0; i < 20; i++) {
            System.out.println("在学习多线程"+i);
        }
    }

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

        //创建runnable接口的实现类对象
        TestThread2 testThread2=new TestThread2();
        //创建线程对象,通过线程对象开启线程,代理
        //Thread thread=new Thread(testThread2);
        //调用start()方法开启线程
        //thread.start();
        new Thread(testThread2).start();        //合并一行

        for (int i = 0; i < 20; i++) {
            System.out.println("在看主线程啊啊啊啊啊"+i);
        }
    }
}

  
  
③实现Callable接口 (了解)

  step1:实现Callable接口,需要返回值类型
  step2:重写call方法,需要抛出异常
  step3:创建目标对象
  step4:创建执行服务:ExecutorService ser = Executors.newFixedThreadPool(1);
  step5:提交执行:Future r1= ser.submit(t1);
  step6:获取结果:boolean result1 = r1.get()
  step7:关闭服务:ser.shutdownNow();

callable好处
1.可以定义返回值
2.可以抛出异常

public class TestThread3 implements Callable<Boolean> {

    @Override
    public Boolean call() {
        System.out.println(Thread.currentThread().getName()+"    Callable线程!!!!");
        return true;
    }

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

        TestThread3 callThread1=new TestThread3();
        TestThread3 callThread2=new TestThread3();
        TestThread3 callThread3=new TestThread3();

        //创建执行服务
        ExecutorService ser= Executors.newFixedThreadPool(3);
        //提交执行
        Future<Boolean> r1=ser.submit(callThread1);
        Future<Boolean> r2=ser.submit(callThread2);
        Future<Boolean> r3=ser.submit(callThread3);

        //获取结果
        boolean result1=r1.get();
        boolean result2=r2.get();
        boolean result3=r3.get();
        System.out.println(result1);
        System.out.println(result2);
        System.out.println(result3);

        //关闭服务
        ser.shutdown();

        System.out.println("在看主线程啊啊啊啊啊");
    }
}

  


2.初识并发 (买火车票+龟兔赛跑)

买火车票
  多个线程操作同一个资源,线程不安全,数据紊乱
  Thread.currentThread():获取当前线程的引用,既代码段正在被哪一个线程调用。

//多个线程操作同一个对象
//买火车票
//发现问题:
public class TestThread implements Runnable{

    //票数
    private int ticketNums=10;

    @Override
    public void run() {
        while (true){
            if(ticketNums<=0){
                break;
            }
            //模拟延时
            try{
                Thread.sleep(200);
            }catch (InterruptedException e){
                e.printStackTrace();
            }

            System.out.println(Thread.currentThread().getName()+"--》拿到了"+ticketNums+"票");
            ticketNums--;
        }
    }

    public static void main(String[] args) {
        TestThread ticketThread=new TestThread();

        new Thread(ticketThread,"老师").start();
        new Thread(ticketThread,"小明").start();
        new Thread(ticketThread,"黄牛").start();
    }
}

  
龟兔赛跑
  1. 首先来个赛道距离,然后要离终点越来越近
  2. 判断比赛是否结束
  3. 打印出胜利者
  4. 龟兔赛跑开始
  5. 故事中是乌龟赢的,兔子需要睡觉,所以我们来模拟兔子睡觉
  6. 终于,乌龟赢得比赛

//模拟龟兔赛跑
public class RaceThread implements Runnable{

    //胜利者
    private static String winner;

    @Override
    public void run() {
        for (int i = 0; i <= 100; i++) {
            //模拟兔子休息
            if(Thread.currentThread().getName().equals("兔子啊")){
                try{
                    Thread.sleep(1);
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
            }

            //判断比赛是否结束
            boolean flg=gameOver(i);
            //比赛结束停止程序
            if (flg){
                break;
            }
            System.out.println(Thread.currentThread().getName()+"-->跑了"+i+"步");
        }
    }

    //判断是否完成比赛
    private boolean gameOver(int steps){
        //判断是否有胜利者
        if(winner!=null){       //已存在胜利者
            return true;
        }{
            if(steps>=100){
                winner=Thread.currentThread().getName();
                System.out.println("winner is"+winner);
                return true;
            }
        }
        return false;
    }


    public static void main(String[] args) {
        RaceThread raceThread=new RaceThread();

        new Thread(raceThread,"兔子啊").start();
        new Thread(raceThread,"乌龟").start();
    }
}

  


3.1 静态代理

实现静态代理对比Thread
  真实对象和代理对象都要实现同一个接口
  代理对象要代理真实角色

好处:
  代理对象可以做很多真实对象做不了的事情
  真实对象专注做自己的事情

new Thread(()-> System.out.println("love")).start();
new WeddingCompany(new You()).HappyMarry();

Thread相当于一个代理,实现了接口Runnable,进行.start()。
婚庆公司代理模拟代码:

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

        new Thread(()-> System.out.println("love")).start();
        new WeddingCompany(new You()).HappyMarry();

        //You you=new You();
        //WeddingCompany weddingCompany=new WeddingCompany(you);
        //wedingCompany.HappyMarry();
    }

}

interface Marry{
    void HappyMarry();
}


//真实角色
class You implements Marry{
    @Override
    public void HappyMarry() {
        System.out.println("you结婚超开心");
    }
}

//代理角色,帮助你结婚
class WeddingCompany implements Marry{
    //代理  真实目标角色
    private Marry target;
    public WeddingCompany(Marry target) {
        this.target = target;
    }

    @Override
    public void HappyMarry() {
        before();
        this.target.HappyMarry();       //这就是真实对象
        after();
    }

    private void before() {
        System.out.println("结婚前,布置现场");
    }

    private void after() {
        System.out.println("结婚之后,收尾款");
    }
}

  

3.2 Lambda表达式 λ

  λ希腊字母表中排序第十一位的字母,英语名称为Lambda
  避免匿名内部类定义过多
  其实质属于函数式编程的概念

(params) -> expression [ 表达式 ]
(params) -> statement [ 语句 ]
(params) -> { statements }

new Thread(()-> System.out.println("λ表达式")).start();

1.为什么使用lamdba表达式
  避免内部类定义过多
  让代码更简洁
  去掉了没有意义的代码,只留下核心的逻辑

2.理解Functional Interface函数式接口
  Runnable接口式函数式接口
  任何接口,如果只包含唯一一个抽象方法,那么它就是一个函数式接口。
  对于函数式接口,我们可以通过lamdba表达式来表达创建该接口的对象。

public interface Runnable{
    public abstract void run();
}

推导lambda表达式:

//推导lambda表达式
public class TestLambda_1 {

    public static void main(String[] args) {

        ILike like=new Like1();    //1.实现类
        like.lambda();

        like=new Like2();          //2.静态内部类
       like.lambda();

        //3.局部内部类
        class Like3 implements ILike{
            @Override
            public void lambda() {
                System.out.println("i like lambda 333");
            }
        }
        like=new Like3();           //3.局部内部类
        like.lambda();


        //4.匿名内部类,没有类的名称,必须借助接口或者父类
        like=new ILike() {
            @Override
            public void lambda() {
                System.out.println("i like lambda 4444");
            }
        };
        like.lambda();              //4.匿名内部类


        //5.用lambda简化
        like=()->{
                System.out.println("i like lambda 55555");
            };
        like.lambda();              //5.用lambda简化 + 0.函数式接口

    }


    //2.静态内部类
    static class Like2 implements ILike{
        @Override
        public void lambda() {
            System.out.println("i like lambda 22");
        }
    }

}

//0.定义一个函数式接口,只包含唯一一个抽象方法的接口
interface ILike{
    void lambda();
}

//1.实现类
class Like1 implements ILike{
    @Override
    public void lambda() {
        System.out.println("i like lambda 1");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Kimberly_zxy

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

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

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

打赏作者

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

抵扣说明:

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

余额充值