【小白学java】D35》》》线程入门学习,线程(多线程)的实现

在这里插入图片描述


🧡💛💚💙💜🤎💗🧡💛💚💙💜🤎💗
感谢各位一直以来的支持和鼓励 制作不易
🙏🙏🙏 求点赞 👍 👍 👍 ➕ 收藏 ⭐ ⭐ ⭐ ➕ 关注✅✅✅
一键三连走起 ! ! !
🧡💛💚💙💜🤎💗 🧡💛💚💙💜🤎💗


【友情链接】➡➡▶线程入门学习,线程同步机制 和 线程等待与唤醒机制
【友情链接】➡➡▶线程入门学习,线程池 & Lambda表达式


一、并发和并行

        并发:指两个或多个事件在同一个时问段内发生。(交替执行)

可以理解为在一段时间内,cpu在多个任务之间交替执行;就好比小屁孩吃苹果和桃,左手拿苹果,右手拿桃,先吃一口苹果,再吃一口桃,然后又回来吃一口苹果,交替着吃苹果和桃,这也就是交替执行

        并行:指两个或多个事件在同一时刻发生(同时发生).(并行执行)

大家还记得小时候老师让我们用 “一边…一边…” 来造句吗?哈哈,小北来造个句,小明一边看电视一边听歌。那么这里的看电视和听歌就是在同时进行着,,,这也就是并行执行。

二、进程和线程

(1)进程

        进程是指内存中正在运行的程序

  • 进程是系统进行资源分配和调用的独立单位
  • 每一个进程都有它自己的内存空间和系统资源
  • 进程指当前正在执行的程序,代表一个应用程序在内存中的执行区域

(2)线程

        线程是进程中单个顺序控制流,是一条执行路径

  • 线程是进程中的一个执行控制单元,执行路径。
  • 单线程:一个进程如果只有一条执行路径,则称为单线程
  • 多线程:一个进程如果有多个执行路径,则称为多线程

注意:
         进程只是负责开辟内存空间的,线程才是负责执行代码逻辑的执行单元。

三、线程具有随机性

        因为在某一个时刻CPU只能执行一个程序,所以当多个程序同时执行时,其实就是CPU在做着快速的切换完成的,这样就可能造成执行代码打印数据时,数据的不规律。详细分析一下线程的执行步骤:Java虚拟机执行main()方法时,首先会找操作系统(OS)开辟一条main()方法通向CPU的路径,这个路径就是main线程(或者“主线程”),那么CPU就可以通过这条路经来执行main()方法,而在main()方法中,通过创建Thread类的子类对象,来调用执行start()方法时,会开辟一条新的通向CPU的新路径来执行run()方法,此时对于CPU来说就有了两条路经了,所以CPU就会随机选择一条路劲执行,那么这样就会导致线程的随机执行。

四、线程的调度

  • 1.分时调度
            程序中的所有线程会轮流使用CPU的使用权,CPU平均分配每个线程占用CPU的时间。
  • 2.抢占式调度
            优先让优先级高的线程使用CPU,如果线程的优先级相同,那么CPU就会随机选择一个线程执行(这也就是线程的随机性), Java使用的就是抢占式调度。

五、多线程的实现原理

在这里插入图片描述

六、通过Thread类实现多线程

(1)Thread类实现多线程的方式步骤:

  • 1.自定义一个类继承Thread类
  • 2.在类中重写run方法
  • 3.创建类的对象
  • 4.启动线程

(2)重写run方法的原因

  • run方法中的内容是用来封装被线程执行的代码

(3)run()方法和start()方法的区别:

  • run():用来封装线程执行的代码,可以直接调用
  • start():该方法用来启动线程,也就是开辟一个新的栈内存,然后再由JVM调用此线程的run()方法

(4)Thread类中获取线程名称的方法

1.使用Thread类中的getName()方法

string getName():返回该线程的名称。

示例·代码:

//创建一个MyThread类
public class MyThread extends  Thread {
    //重写run()方法
    @Override
    public void run() {
        //调用getName()方法获取线程名称
        String mtName =getName();
        System.out.println(mtName);
    }
}
//创建一个test测试类
public class test {
    public static void main(String[] args) {
        //创建MyThread类对象
        MyThread myThread = new MyThread();
        //调用start()方法,开启线程
        myThread.start();

        new MyThread().start();
        new MyThread().start();
        new MyThread().start();
        new MyThread().start();
    }
}

测试结果:
在这里插入图片描述

2.获取当前正在执行的线程

static Thread currentThread():返回对当前正在执行的线程对象的引用。

示例代码:

public class MyThread extends  Thread {
    //重写run()方法
    @Override
    public void run() {
        //获取线程
        Thread currentThread =  Thread.currentThread();
        System.out.println(currentThread);
        //打印线程名
        System.out.println(currentThread.getName());
    }
}
//创建一个test测试类
public class test {
    public static void main(String[] args) {
        //创建MyThread类对象
        MyThread myThread = new MyThread();
        //调用start()方法,开启线程
        myThread.start();

        new MyThread().start();
        new MyThread().start();
        new MyThread().start();
        new MyThread().start();
    }
}

测试结果:
在这里插入图片描述

(5)Thread类中设置线程名称的方法

1.使用Thread类中的方法setName()

void setName(String name)  改变线程名称

⒉创建一个带参数的构造方法,参数传递线程的名称,调用父类(Thread)的带参构造方法,把线程名称传递给父类,让父类给子线程起一个名字

 Thread(string name)    分配新的Thread对象。

示例代码:

//创建MyThread类继承Thread类
public class MyThread extends  Thread {

    public  MyThread(){}

    public MyThread(String s) {
      super(s);//将名称传给父类,让父类给线程起名
    }

    //重写run()方法
    @Override
    public void run() {
        //打印线程名
        System.out.println(Thread.currentThread().getName());

    }
}

//创建一个test测试类
public class test {
    public static void main(String[] args) {
        //创建MyThread类对象
        MyThread myThread = new MyThread();
        //设置线程名称
        myThread.setName("我是自定义线程hello");
        //调用start()方法,开启线程
        myThread.start();

        new MyThread("我是自定义线程world").start();

    }
}

测试结果:
在这里插入图片描述

七、通过Runnable实现多线程

        java.lang包下的Runnable 接口应该由那些打算通过某一线程执行其实例的类来实现。而类中必须定义一个名为 run的无参数方法,run方法

Thread类的构造方法有

Thread( Runnable target)  分配新的Thread 对象。
Thread ( Runnoble target,string name) 分配新的Thread对象。

实现步骤:

  • 1.创建一个类实现Runnable接口
  • 2.在类中重写Runnable接口的run()方法,设置线程的任务
  • 3.创建实现类的对象
  • 4.创建Thread对象,把实现类的对象作为构造方法的参数
  • 5.调用Thread类的start()方法,启动线程,执行run()方法

示例代码:

//1.创建一个类实现Runnable接口
public class RunnableImp implements Runnable {
    //2.在类中重写Runnable接口的run()方法,设置线程的任务
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName()+"-->"+i);
        }
    }
}

public class test {
    public static void main(String[] args) {
        //3.创建实现类的对象
        RunnableImp runnableImp = new RunnableImp();
        //4.创建Thread对象,把实现类的对象作为构造方法的参数
        Thread thread = new Thread(runnableImp);
        //5.调用Thread类的start()方法,启动线程,执行run()方法
        thread.start();


        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName()+"-->"+i);
        }
    }
}

测试结果: 抢占执行

在这里插入图片描述

八、两种实现多线程的方式的区别

        java中的继承都是单继承,不利于资源共享,所以当一个类继承Thread类来实现多线程时,就不适合资源共享。但如果一个类通过实现Runable接口来实现多线程,同时该实现类还可以实现其他的接口,或继承其他的类,那么就很容易实现资源共享,大大提高程序的效率。

实现Runnable接口比继承Thread类所具有的优势:

  • 1.通过Runnable接口实现多线程,适合有多个相同的程序代码的线程去共享同一个资源。
  • 2.通过Runnable接口实现多线程,可以避免java中单继承的局限性。
  • 3.通过Runnable接口实现多线程,可以增加程序的健社性(扩展性),降低程序的耦合性(实现解耦操作),代码可以被多个线程共享,代码和线程又相互独立。

注意: 通过Runnable接口实现多线程,将设置线程任务和开辟一个新的线程分离开了(这也就是解耦),在实现类中重写run()方法来设置线程任务,通过Thread类的对象,调用start()方法来开辟一个新的线程

  • 4.线程池中只能放入实现Runnable或Callable类线程,而不能直接放入继承Thread的类。

九、通过匿名内部类实现线程的创建

匿名内部类的详细介绍,链接:
【小白学Java】D18》》》匿名类&匿名对象&内部类

测试代码:

public class Task {
    public static void main(String[] args) {
        /**
        * 匿名内部类使用格式;
        * new  父类/接口(){
        *       //重写父类/接口中的方法
        *  };
        * */

        //Thread类实现多线程
        new Thread(){
            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {
                    System.out.println(Thread.currentThread().getName()+"-->"+"Thread");
                }
            }
        }.start();

        //Runnable接口实现多线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {
                    System.out.println(Thread.currentThread().getName()+"-->"+"Runnable");
                }
            }
        }).start();
    }
}

测试结果:
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

北慕辰

你的鼓励是小北最大的动力

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

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

打赏作者

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

抵扣说明:

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

余额充值