当前位置: 首页 > news >正文

java多线程-基础

1. 基本用法

总共两种,

第一种:继承Runnbale接口,实现run方法

Runnable r = new Runnable() {
    @Override
    public void run() {

    System.out.println("123");

    }
};

Thread thread = new Thread(r);
thread.start();    

 

第二种:继承Thread类,重写run方法

class MyThread extends Thread{

    @Override
    public void run() {
        for(int i = 0;i<10;i++){
            System.out.println(Thread.currentThread().getName());
        }
    }
}

调用的时候

MyThread myThread = new MyThread();
myThread.start();

 

总结:两种的区别是,没区别,两种都需要new一个Thread的实例,第一种就是传入Runnable实例,当Thread类的run被调用的时候,调用Runnable的run方法。第二种是重写Thread的run方法,意思就是说,不执行父类Thread里面的run方法了,直接执行你重写的run里面的内容,所以结果也是一样。如果当前类已继承了一个父类,不能继承Thread,那么就可以考虑继承Runnable接口。个人认为继承Runnable接口更家灵活。

 

2. 线程随机性

这里就写了一段代码,测试效果,可以看出来,每次执行的结果都是不一样的,证明,线程具有随机与不确定性,Thread的start方法就是告诉CPU,线程准备就绪,等待CPU的调用run方法,所以当CPU空闲的时候,他就会去调用run的方法。所以为什么上面的代码里面调用的是start而不是run,因为调用start最终的结果是由另外一个线程调起run方法,而如果一开始调用run,那就不是在同一个线程当中执行。切记这一点

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

        MyThread myThread = new MyThread();
        myThread.start();

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


}
class MyThread extends Thread{

    @Override
    public void run() {
        for(int i = 0;i<10;i++){
            System.out.println(Thread.currentThread().getName());
        }
    }
}

 

第一次执行结果:

 

第二次执行结果:

 

3. 调用start顺序不代表线程启动顺序

这里写了一段代码测试,循环新建线程并调用start,按顺序应该从0到9,但结果并没有,每一次运行的结果都不一样,而且是无序,代表start的顺序并不代表run被调用的顺序

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

        for(int i = 0;i<10;i++){
            MyThread myThread = new MyThread(i);
            myThread.start();

        }
    }


}
class MyThread extends Thread{

    private int ti;
    public MyThread(int ti){
        this.ti = ti;
    }

    @Override
    public void run() {
        System.out.println("Thread_" + ti);
    }
}

 

第一次运行结果:

 

第二次运行结果:

 

 

转载于:https://www.cnblogs.com/oscar1987121/p/10219595.html

相关文章:

  • wordpress在撰写新文章界面的显示选项按钮点击无反应的解决办法
  • opengl——贴图
  • learnopengl——Framebuffers
  • learnopengl——纹理
  • [转帖]Application Request Route实现IIS Server Farms集群负载详解
  • learnopengl——三角形
  • songho——OpenGL的帧缓冲
  • while 循环 及 and or not
  • songho——OpenGL的顶点缓冲对象
  • OGL(教程35)——延迟渲染1——代码结构梳理
  • 安装MySQL_安装Navicat_启动数据库服务
  • android studio查看android手机日志
  • Python02(Linux命令)
  • luaforwindws安装与调用方式
  • vs添加链接文件
  • chrome扩展demo1-小时钟
  • hadoop入门学习教程--DKHadoop完整安装步骤
  • HTTP--网络协议分层,http历史(二)
  • JavaScript设计模式与开发实践系列之策略模式
  • Java精华积累:初学者都应该搞懂的问题
  • ng6--错误信息小结(持续更新)
  • nginx 配置多 域名 + 多 https
  • Swift 中的尾递归和蹦床
  • vue-router的history模式发布配置
  • WebSocket使用
  • 阿里云Kubernetes容器服务上体验Knative
  • 大整数乘法-表格法
  • 多线程 start 和 run 方法到底有什么区别?
  • 如何用vue打造一个移动端音乐播放器
  • 小程序滚动组件,左边导航栏与右边内容联动效果实现
  • 一份游戏开发学习路线
  • Android开发者必备:推荐一款助力开发的开源APP
  • k8s使用glusterfs实现动态持久化存储
  • 容器镜像
  • 数据可视化之下发图实践
  • #NOIP 2014# day.1 生活大爆炸版 石头剪刀布
  • #传输# #传输数据判断#
  • (C语言)输入自定义个数的整数,打印出最大值和最小值
  • (Redis使用系列) Springboot 使用redis实现接口Api限流 十
  • (保姆级教程)Mysql中索引、触发器、存储过程、存储函数的概念、作用,以及如何使用索引、存储过程,代码操作演示
  • (二)什么是Vite——Vite 和 Webpack 区别(冷启动)
  • (力扣记录)1448. 统计二叉树中好节点的数目
  • (利用IDEA+Maven)定制属于自己的jar包
  • (一)为什么要选择C++
  • **Java有哪些悲观锁的实现_乐观锁、悲观锁、Redis分布式锁和Zookeeper分布式锁的实现以及流程原理...
  • .bashrc在哪里,alias妙用
  • .NET 反射 Reflect
  • .NET/C# 反射的的性能数据,以及高性能开发建议(反射获取 Attribute 和反射调用方法)
  • /usr/bin/python: can't decompress data; zlib not available 的异常处理
  • @GetMapping和@RequestMapping的区别
  • @KafkaListener注解详解(一)| 常用参数详解
  • @Resource和@Autowired的区别
  • [ Linux ] git工具的基本使用(仓库的构建,提交)
  • [C++] Windows中字符串函数的种类
  • [CISCN 2023 初赛]go_session