• Java多线程-用代码编程实现模拟机器人对话


     个人简介

    👨🏻‍💻个人主页:陈橘又青

    🏃🏻‍♂️博客记录心情,代码编写人生。

    🌟如果文章对你有用,麻烦关注点赞收藏走一波,感谢支持!

    🌱欢迎订阅我的专栏:【Java进阶之路】带你入门Java,从0到1。

                                         【Java全栈编程】带你项目实战,掌握核心。


    前言

    今天带大家来体验一下Java多线程,首先我们要明白什么是线程?什么是多线程?

    进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程。比如在Windows系统中,一个运行的exe就是一个进程。

    线程是指进程中的一个执行流程,一个进程可以运行多个线程。比如java.exe进程可以运行很多线程。线程总是输入某个进程,进程中的多个线程共享进程的内存。

    多线程指的是这个程序(一个进程)运行时产生了不止一个线程。

    目录

    一、Java多线程的介绍

    二、创建线程并运行

    三、多线程间的交互

    ①实践模拟两个机器人对话


    一、Java多线程的介绍

    我们知道,Java编写程序都运行在在Java虚拟机JVM)中,在JVM的内部,程序的多任务是通过线程来实现的。每用java命令启动一个java应用程序,就会启动一个JVM进程。在同一个JVM进程中,有且只有一个进程,就是它自己。在这个JVM环境中,所有程序代码的运行都是以线程来运行。

    一般常见的Java应用程序都是单线程的。比如,用java命令运行一个最简单的HelloWorld的Java应用程序时,就启动了一个JVM进 程,JVM找到程序程序的入口点main(),然后运行main()方法,这样就产生了一个线程,这个线程称之为主线程。当main方法结束后,主线程运行完成。JVM进程也随即退出 。

    对于一个进程中的多个线程来说,多个线程共享进程的内存块,当有新的线程产生的时候,操作系统不分配新的内存,而是让新线程共享原有的进程块的内存。因此,线程间的通信很容易,速度也很快。不同的进程因为处于不同的内存块,因此进程之间的通信相对困难

    多线程能满足程序员编写高效率的程序来达到充分利用 CPU 的目的。

    线程是一个动态执行的过程,它也有一个从产生到死亡的过程。

    下图显示了一个线程完整的生命周期:

    42cf1dca1e424dfe8ba5a8644f3eb414.png


     二、创建线程并运行

    接下来,我们使用Thread创建一个线程并运行:

    1.打开Idea新建工程,再右击src新建包Thread,在包上点右键,创建一个PeopleA类,输入代码:

    1. package Thread;
    2. public class PeopleA extends Thread{
    3. @Override
    4. public void run() { //被调用start方法后,就会执行run方法里的代码
    5. System.out.println(this.getName() + " 线程开始执行了:");
    6. try {
    7. Thread.sleep(5000); //休眠5秒,模拟子线程需要5秒才能完成任务。
    8. } catch (InterruptedException e) {
    9. e.printStackTrace();//在命令行打印异常信息在程序中出错的位置及原因。
    10. }
    11. System.out.println(this.getName() + " 线程执行结束了:");
    12. }
    13. }

    2.再右击Thread包创建一个ThreadTest类,并输入代码:

    1. package Thread;
    2. public class ThreadTest {
    3. public static void main(String[] args) {
    4. //在mian 线程(主线程)中创建了一个子线程 peopleA
    5. PeopleA peopleA = new PeopleA();
    6. //给子线程取个名字:A线程
    7. peopleA.setName("A线程");
    8. //启动peopleA线程,启动后系统将增加一个线程去执行PeopleA中的run方法里的代码
    9. peopleA.start();
    10. //打印这句表示主线程启动子线程后,会继续执行后续代码,不会关心子线程什么时候执行
    11. System.out.println("main函数结束了。");
    12. }
    13. }

    3.运行,查看结果,体会多线程的执行:

    主线程启动子线程后,会继续执行后续代码,不会关心子线程什么时候执行。
    这里还需注意,主线程的代码执行完毕后,整个程序并没有立即结束运行,而是等待子线程运行完后再结束运行并回收资源。

    三、多线程间的交互

    ①模拟两个机器人的对话

    1.我们右击src,新建一个包com.my.thread,并右击创建名为Language的对象,用来存储问题和答案,用于2个机器人的交互。代码如下:

    1. package com.my.thread;
    2. import java.util.Random;
    3. //预先设定好可能的对话内容
    4. public class Language {
    5. //问题集合
    6. static final String[] questions = {
    7. "你叫什么名字?",
    8. "现在几点了?",
    9. "你早饭吃的什么?",
    10. "你中午吃的什么?",
    11. "你晚餐吃的什么?",
    12. "你的身高多少?",
    13. "你最喜欢的Csdn博主是谁?"
    14. };
    15. //随机数生成器
    16. static Random random = new Random();
    17. //当前问题
    18. static String question = null;
    19. //当前答案
    20. static String answer = null;
    21. /**随机获取一个问题*/
    22. public static String getARandomQuestion() {
    23. int index = random.nextInt(questions.length);
    24. return questions[index];
    25. }
    26. //设置当前答案
    27. public static void setAnswer(String answer) {
    28. Language.answer = answer;
    29. }
    30. //设置当前问题
    31. public static void setQuestion(String question) {
    32. Language.question = question;
    33. }
    34. }

    2. 在com.my.thread包上创建名为PeopleA的对象,用来模拟提问者。代码如下:

    1. package com.my.thread;
    2. public class PeopleA extends Thread{
    3. @Override
    4. public void run() { //被调用start方法后,就会执行run方法里的代码
    5. System.out.println(this.getName() + " 我要开始提问了。");
    6. //使用死循环写法,让线程PeopleA永远不会自动停止运行
    7. while(true){
    8. //没有人回答问题 并且没有人提问的时候,就提一个问题
    9. if(Language.question == null) {
    10. String q = Language.getARandomQuestion();//获取一个随机问题
    11. Language.setQuestion(q);//设置问题
    12. System.out.println(this.getName() + ":" + q);
    13. Language.setAnswer(null);//提出问题后,把答案设置为空
    14. }else{
    15. System.out.println("请回答我的问题...");
    16. }
    17. try {
    18. //随机休眠0-15秒,模拟用户A的思考时间
    19. Thread.sleep(1000 * Language.random.nextInt(15));
    20. } catch (InterruptedException e) {
    21. e.printStackTrace();
    22. }
    23. }
    24. }
    25. }

    3. 在com.my.thread包上创建名为PeopleB的对象,用来模拟回答者。代码如下:

    1. package com.my.thread;
    2. import java.text.SimpleDateFormat;
    3. import java.util.Date;
    4. public class PeopleB extends Thread{
    5. SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    6. @Override
    7. public void run() { //被调用start方法后,就会执行run方法里的代码
    8. System.out.println(this.getName() + " 我准备好回答了。");
    9. //使用死循环写法,让线程PeopleB永远不会自动停止运行
    10. while(true){
    11. //有人提问,且没有人回答的情况下,就回答问题
    12. if(Language.answer == null) {
    13. String an = answerQuestion(Language.question); //根据问题得到答案
    14. Language.setAnswer(an);//设置答案
    15. System.out.println(this.getName() + ":" + an);//打印答案
    16. Language.question = null;//回答完毕后,把问题设置为空。
    17. }else{
    18. System.out.println("请你继续提问...");
    19. }
    20. try {
    21. //随机休眠0-15秒,模拟用户B的思考时间
    22. Thread.sleep(1000 * Language.random.nextInt(15));
    23. } catch (InterruptedException e) {
    24. e.printStackTrace();
    25. }
    26. }
    27. }
    28. //根据问题得到答案
    29. private String answerQuestion(String question) {
    30. if(question == null){
    31. return "请开始提问...";
    32. }
    33. String an = "这个问题太难了,答不上来。";//默认回答语句
    34. if(question.equals("你叫什么名字?")){
    35. an = this.getName();
    36. }else if(question.equals("现在几点了?")){
    37. an = format.format(new Date());
    38. }else if(question.equals("你早饭吃的什么?")){
    39. an = "豆浆油条。";
    40. }else if(question.equals("你的身高多少?")){
    41. an = "身高1米85。";
    42. }else if(question.equals("你最喜欢的Csdn博主是谁?")){
    43. an = "青00(一起学Java)";
    44. }else{
    45. }
    46. return an;
    47. }
    48. }

     4.创建ThreadTest对象的main函数,启动2个线程,观察运行结果(每次结果可能都不一样):

    1. package com.my.thread;
    2. public class ThreadTest {
    3. public static void main(String[] args) {
    4. //在mian 线程(主线程)中创建了2个子线程 peopleA,peopleB
    5. PeopleA peopleA = new PeopleA();
    6. PeopleB peopleB = new PeopleB();
    7. //给子线程取个名字
    8. peopleA.setName("提问者");
    9. peopleB.setName("回答者");
    10. //启动peopleA,peopleB线程,启动后系统将增加一个线程去执行run方法里的代码
    11. peopleA.start();
    12. peopleB.start();
    13. //打印这句表示主线程启动子线程后,会继续执行后续代码,不会关心子线程什么时候执行
    14. System.out.println("main函数结束了。");
    15. }
    16. }

     5.运行ThreadTest.java,观察结果,体会多线程的工作原理。

    cac4672c74ee402592e7ce6cdf6aeb60.png


    多线程的使用注意事项:有效利用多线程的关键是理解程序是并发执行而不是串行执行的。

    例如:程序中有两个子系统需要并发执行,这时候就需要利用多线程编程。通过对多线程的使用,可以编写出非常高效的程序。

    请注意,如果你创建太多的线程,程序执行的效率实际上是降低了,而不是提升了。请记住,上下文的切换开销也很重要,如果你创建了太多的线程,CPU 花费在上下文的切换的时间将多于执行程序的时间!


     🥰以上就是本篇博客的全部内容,如果对你有用麻烦关注点赞收藏三连走一波!
    👋如有问题欢迎留言,如有错误烦请指正,期待你的评论!

     

     

  • 相关阅读:
    【字母识别】基于matlab BP神经网络英文字母识别【含Matlab源码 2226期】
    【算法】计数排序算法的讲解和代码演示
    numpy对行操作总结
    ::before 和 :after中双冒号和单冒号 有什么区别?解释一下这2个伪元素的作用
    Android:OkHttp同步请求和异步请求
    Go语言用Colly库编写的图像爬虫程序
    C++设计模式_13_Flyweight享元模式
    CompletableFuture 异步编排、案例及应用小案例
    ThreadLocal
    一文带你深入理解【Java基础】· 注解
  • 原文地址:https://blog.csdn.net/m0_63947499/article/details/125300100