java多线程实现的2种方式详解、比较、匿名内部类实现多线程的方法

目录

方式一 继承Thread类

1 步骤

 2 代码

3 程序执行分析

​4 Thread类常用方法

4.1 获取线程的名称

 4.2 设置线程的名称(了解)

 4.3 暂停线程:sleep()

*方法二 : 实现Runnable接口

 1 步骤

2 代码

两种方式的比较

匿名内部类实现线程的方法


关于多线程概念的介绍,请点这里

方式一 继承Thread类


1 步骤


1 创建一个类继承Thread类
2 重写run()方法,设置线程任务(开启线程要做什么)
3 new 对象,调用Thread类的start()方法 → 就会开启新的线程,执行之前写的run()方法了

java使用的为抢占式调度,优先级高的线程先使用CPU,如果优先级相同,就随机选择.

 2 代码

package manyThreads;

public class MyThread extends Thread{
    //重写run()方法,设置线程的任务
    @Override
    public void run() {
        //循环20次
        for (int i = 0; i < 20; i++) {
            System.out.println("run"+i);
        }
    }
}
package manyThreads;


public class MainMethod {
    public static void main(String[] args) {
        //新线程
        MyThread myThread = new MyThread();
        myThread.start();
        //主线程
        for (int i = 0; i < 20; i++) {
            System.out.println("main"+i);
        }
    }
}

结果

3 程序执行分析


1 JVM 执行main方法,操作系统OS开辟了一条 main方法通向CPU的路径,这个路径就叫做 main线程(主线程)
2 当new MyThread(),调start()方法时,OS又开辟了一条新的到CPU的路径,这个路径就是 新线程MyThread,新线程会执行run()方法
3 对于CPU来说就有了2条路径,CPU就有了选择的权利,CPU喜欢谁就执行哪条路径,所以就有了程序的随机打印结果
(两个线程:一个main线程,一个新线程,就会抢夺CPU的执行权,谁抢到了谁执行对应的代码)

 注意:

调用Thread类的start()方法,才会开启新的线程路径

如果直接执行run()方法,还是用的原来的线程

4 Thread类常用方法

4.1 获取线程的名称


    方法1:Thread类的getName()方法
    方法2:Thread.currentThread().getName()
    
主线程默认名称:main
新线程默认名称:Thread-0 Thread-1 Thread-2 Thread-3 ...

 4.2 设置线程的名称(了解)


    方法1:setName()
    方法2:创建一个带参的构造方法,把线程名称传递给父类让父类给子线程起个名字

package manyThreads;

import androidx.annotation.NonNull;

public class MyThread extends Thread{

    public MyThread() {
    }

    //方法2:创建一个带参的构造方法,把线程名称传递给父类让父类给子线程起个名字
    public MyThread(@NonNull String name) {
        super(name);
    }

    //重写run()方法,设置线程的任务
    @Override
    public void run() {
        //获取线程的名称
        System.out.println(getName());
    }
}

package manyThreads;


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

        //方法一:setName()
        MyThread myThread = new MyThread();
        myThread.setName("小名");
        myThread.start();
        //方法二:创建一个带参的构造方法,把线程名称传递给父类让父类给子线程起个名字
        MyThread myThread2 = new MyThread("阿树");
        myThread2.start();


    }
}

 运行结果

 4.3 暂停线程:sleep()


    使当前正在执行的线程暂停指定的毫秒,毫秒数结束之后,线程继续执行

执行结果:隔1s打印一个数字

*方法二 : 实现Runnable接口

 1 步骤


1 创建一个类,实现Runnable接口
2 重写run()方法,设置线程任务
3 new Runnable接口的实现对象
4 创建一个Thread类对象,构造方法中传递Runnable接口的实现对象
5 调用Thread类的start()方法

2 代码

package manyThreads;

public class MyThreadRunnable implements Runnable{
    @Override
    public void run() {

        for (int i = 0; i < 20; i++) {
            System.out.println(Thread.currentThread().getName()+"之"+i);

        }
    }
}
package manyThreads;


public class MainMethod {
    public static void main(String[] args) {
        MyThreadRunnable myThreadRunnable = new MyThreadRunnable();
        Thread thread = new Thread(myThreadRunnable);
        thread.start();
        for (int i = 0; i < 20; i++) {
            System.out.println(Thread.currentThread().getName()+"之"+i);

        }

    }
}

执行结果

两种方式的比较

实现Runnable接口的好处
1 避免的单继承的局限性 (一个类只能继承一个类,一个人只能有1个亲爹)
     实现Runnable接口还可以继承其他类,实现其他接口


2 增强了程序的扩展性,降低了程序的耦合性(解耦)     
    实现Runnable接口 把设置线程任务和开启新线程进行了分离
    设置线程任务:Runnable接口中重写run()方法
    开启新线程:创建的Thread类调用start()方法
    
    

匿名内部类实现线程的方法

匿名:没有名字
内部类:写在其他类内部的类

匿名内部类的作用:简化代码
匿名内部类的最终产物:子类/实现类对象,而这个类没有名字
匿名内部类的格式:
    new 父类/接口(){
        重写父类/接口中的方法
    }

代码

package nimingThread;


import manyThreads.MyThreadRunnable;

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

        //1 线程的父类是Thread
        new Thread() {
            @Override
            public void run() {
                for (int i = 0; i < 20; i++) {
                    System.out.println(Thread.currentThread().getName() + "继承");

                }
            }
        }.start();


        //2 线程的接口是Runnable
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 20; i++) {
                    System.out.println(Thread.currentThread().getName() + "实现接口");

                }
            }
        }).start();


    }
}

结果

关于线程的安全问题及解决办法

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值