学习路线指引(点击解锁) | 知识定位 | 人群定位 |
---|---|---|
🧡 Python实战微信订餐小程序 🧡 | 进阶级 | 本课程是python flask+微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一个全栈订餐系统。 |
💛Python量化交易实战💛 | 入门级 | 手把手带你打造一个易扩展、更安全、效率更高的量化交易系统 |
进程:
线程:
其他相关概念:
例子:
| | package li.thread; |
| | |
| | public class CpuNum { |
| | public static void main(String[] args) { |
| | |
| | Runtime runtime = Runtime.getRuntime(); |
| | //获取当前的电脑的cpu数量 |
| | int cpuNums = runtime.availableProcessors(); |
| | System.out.println("当前的CPU数量="+cpuNums);//当前的CPU数量=8 |
| | |
| | } |
| | } |
在java中线程来使用有两种方法:
例子1:线程应用案例1-继承Thread类
1)请编写程序,开启一个线程,该线程每隔一秒,在控制台输出 “喵喵,我是小猫咪”
2)对上题改进:当输出80次“喵喵,我是小猫咪”时,结束该线程
3)使用JConsole监控线程执行情况,并画出程序示意图
| | package li.thread; |
| | |
| | //演示通过继承Thread类创建线程 |
| | public class Thread01 { |
| | public static void main(String[] args) throws InterruptedException { |
| | |
| | //创建一个Cat对象,可以当做线程来使用 |
| | Cat cat = new Cat(); |
| | |
| | cat.start();//启动线程 |
| | |
| | //当main线程启动一个子线程 Thread-0后,主线程不会阻塞,会继续执行 |
| | //这时 主线程和子线程是交替执行 |
| | System.out.println("主线程继续执行="+Thread.currentThread().getName());//主线程继续执行=main |
| | for (int i = 0; i < 60; i++) { |
| | System.out.println("主线程 i="+i); |
| | //让主线程休眠 |
| | Thread.sleep(1000); |
| | } |
| | } |
| | } |
| | |
| | //1.当一个类继承了Thread类,该类就可以当做一个线程使用 |
| | //2.我们会重写run方法,写上自己的业务代码 |
| | //3.run Thread类实现了Runnable接口的run方法 |
| | /* |
| | @Override |
| | public void run() { |
| | if (target != null) { |
| | target.run(); |
| | } |
| | } |
| | */ |
| | class Cat extends Thread { |
| | @Override |
| | public void run() {//重写run方法,写上自己的业务逻辑 |
| | int times = 0; |
| | while (true) { |
| | //该线程每隔1秒,在控制台输出 “喵喵,我是小猫咪” |
| | System.out.println("喵喵,我是小猫咪" + (++times)+" 线程名称="+Thread.currentThread().getName()); |
| | //让该线程休眠一秒 |
| | try { |
| | Thread.sleep(1000);//单位为毫秒 try-catch快捷键:Ctrl+Alt+T |
| | } catch (InterruptedException e) { |
| | e.printStackTrace(); |
| | } |
| | if (times == 80) { |
| | break;//当times到80,退出while,这是线程也就退出了 |
| | } |
| | } |
| | } |
| | } |
3)使用JConsole监控线程执行情况,并画出程序示意图:
如下,在控制台点击run,运行程序,在程序运行时,点击Termial
在控制台输入JConsole,回车。
点击本地进程,点击Thread01,点击下方连接按钮:
在弹出窗口中点击不安全的连接按钮:
在窗口中点击“线程”:
可以在左下角的线程小窗口中看到main线程和Thread-0线程在同时进行
等待一段时间,可以看到当run窗口的主线程 i = 60之后,main线程结束
结束前:
结束后:
当线程名称=Thread-0输出到80次时,虽然可以Thread-0还在左下角,但是实际上Thread-0线程已经结束了,整个进程随之结束。
程序示意图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7GcHdoWc-1662225042162)(https://liyuelian.oss-cn-shenzhen.aliyuncs.com/imgs/%E7%BA%BF%E7%A8%8B%E7%9A%84%E5%9F%BA%E6%9C%AC%E4%BD%BF%E7%94%A8.png)]
注意:在多线程编程里面,并不一定说主线程结束了,整个进行就结束了,等所有线程都结束了,进程才会结束。
在2.1的例子中,主方法中定义了cat对象,该对象调用了start方法,start方法会去启动一个线程,最终会执行Cat 类的run方法。
思考一个问题:既然最终都是要调用run方法,为什么cat对象还要通过start方法对调用run呢?为什么不直接调用?
答案: 首先通过 对象.run() 方法 可以执行方法,但是不是使用的多线程的方式,就是一个普通的方法,没有真正地启动一个线程。即这时候把run方法执行完毕,才能执行主方法剩下的语句。
如下图:将cat.start();
改为cat.run();
之后的运行结果:
在run方法执行完之后才执行主方法剩下的语句
那么在调用start方法时,整个过程到底是什么样子的?
点击start()方法:可以在start方法中看到一个start0()方法:
点击start0( )方法:可以看到start0是一个本地方法,由 JVM调用,底层是c/c++实现。
再看看run()方法的源码:可以看到run方法只是简单的调用了实现类的run,没有进行任何的多线程处理。
换而言之,Java中真正实现多线程的效果的是start0方法,而不是run方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mYXqC6Fn-1662225042167)(https://liyuelian.oss-cn-shenzhen.aliyuncs.com/imgs/start0%E6%96%B9%E6%B3%95.png)]