Java實現模擬機器人對話的示例代碼

前言

今天帶大傢來體驗一下Java多線程,首先我們要明白什麼是線程?什麼是多線程?

進程是指一個內存中運行的應用程序,每個進程都有自己獨立的一塊內存空間,一個進程中可以啟動多個線程。比如在Windows系統中,一個運行的exe就是一個進程。

線程是指進程中的一個執行流程,一個進程可以運行多個線程。比如java.exe進程可以運行很多線程。線程總是輸入某個進程,進程中的多個線程共享進程的內存。

多線程指的是這個程序(一個進程)運行時產生瞭不止一個線程。

一、Java多線程的介紹

我們知道,Java編寫程序都運行在在Java虛擬機JVM)中,在JVM的內部,程序的多任務是通過線程來實現的。每用java命令啟動一個java應用程序,就會啟動一個JVM進程。在同一個JVM進程中,有且隻有一個進程,就是它自己。在這個JVM環境中,所有程序代碼的運行都是以線程來運行。

一般常見的Java應用程序都是單線程的。比如,用java命令運行一個最簡單的HelloWorld的Java應用程序時,就啟動瞭一個JVM進 程,JVM找到程序程序的入口點main(),然後運行main()方法,這樣就產生瞭一個線程,這個線程稱之為主線程。當main方法結束後,主線程運行完成。JVM進程也隨即退出 。

對於一個進程中的多個線程來說,多個線程共享進程的內存塊,當有新的線程產生的時候,操作系統不分配新的內存,而是讓新線程共享原有的進程塊的內存。因此,線程間的通信很容易,速度也很快。不同的進程因為處於不同的內存塊,因此進程之間的通信相對困難

多線程能滿足程序員編寫高效率的程序來達到充分利用 CPU 的目的。

線程是一個動態執行的過程,它也有一個從產生到死亡的過程。

下圖顯示瞭一個線程完整的生命周期:

 二、創建線程並運行

接下來,我們使用Thread創建一個線程並運行:

1.打開Idea新建工程,再右擊src新建包Thread,在包上點右鍵,創建一個PeopleA類,輸入代碼:

package Thread;
 
public class PeopleA extends Thread{
    @Override
    public void run() { //被調用start方法後,就會執行run方法裡的代碼
        System.out.println(this.getName() + " 線程開始執行瞭:");
        try {
            Thread.sleep(5000); //休眠5秒,模擬子線程需要5秒才能完成任務。
        } catch (InterruptedException e) {
        e.printStackTrace();//在命令行打印異常信息在程序中出錯的位置及原因。
        }
        System.out.println(this.getName() + " 線程執行結束瞭:");
    }
}

2.再右擊Thread包創建一個ThreadTest類,並輸入代碼:

package Thread;
 
public class ThreadTest {
    public static void main(String[] args) {
        //在mian 線程(主線程)中創建瞭一個子線程 peopleA
        PeopleA peopleA = new PeopleA();
        //給子線程取個名字:A線程
        peopleA.setName("A線程");
        //啟動peopleA線程,啟動後系統將增加一個線程去執行PeopleA中的run方法裡的代碼
        peopleA.start();
        //打印這句表示主線程啟動子線程後,會繼續執行後續代碼,不會關心子線程什麼時候執行
        System.out.println("main函數結束瞭。");
    }
}

3.運行,查看結果,體會多線程的執行:

主線程啟動子線程後,會繼續執行後續代碼,不會關心子線程什麼時候執行。
這裡還需註意,主線程的代碼執行完畢後,整個程序並沒有立即結束運行,而是等待子線程運行完後再結束運行並回收資源。

三、多線程間的交互

①模擬兩個機器人的對話

1.我們右擊src,新建一個包com.my.thread,並右擊創建名為Language的對象,用來存儲問題和答案,用於2個機器人的交互。代碼如下:

package com.my.thread;
 
import java.util.Random;
 
//預先設定好可能的對話內容
public class Language {
    //問題集合
    static final String[] questions = {
            "你叫什麼名字?",
            "現在幾點瞭?",
            "你早飯吃的什麼?",
            "你中午吃的什麼?",
            "你晚餐吃的什麼?",
            "你的身高多少?",
            "你最喜歡的Csdn博主是誰?"
    };
    //隨機數生成器
    static Random random = new Random();
    //當前問題
    static String question = null;
    //當前答案
    static String answer = null;
 
    /**隨機獲取一個問題*/
    public static String getARandomQuestion() {
        int index = random.nextInt(questions.length);
        return questions[index];
    }
    //設置當前答案
    public static void setAnswer(String answer) {
        Language.answer = answer;
    }
    //設置當前問題
    public static void setQuestion(String question) {
        Language.question = question;
    }
}

2. 在com.my.thread包上創建名為PeopleA的對象,用來模擬提問者。代碼如下:

package com.my.thread;
 
public class PeopleA extends Thread{
    @Override
    public void run() { //被調用start方法後,就會執行run方法裡的代碼
        System.out.println(this.getName() + " 我要開始提問瞭。");
 
        //使用死循環寫法,讓線程PeopleA永遠不會自動停止運行
        while(true){
            //沒有人回答問題 並且沒有人提問的時候,就提一個問題
            if(Language.question == null) {
                String q = Language.getARandomQuestion();//獲取一個隨機問題
                Language.setQuestion(q);//設置問題
                System.out.println(this.getName() + ":" + q);
                Language.setAnswer(null);//提出問題後,把答案設置為空
            }else{
                System.out.println("請回答我的問題...");
            }
 
            try {
                //隨機休眠0-15秒,模擬用戶A的思考時間
                Thread.sleep(1000 * Language.random.nextInt(15));
 
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
 
    }
}

3. 在com.my.thread包上創建名為PeopleB的對象,用來模擬回答者。代碼如下:

package com.my.thread;
 
import java.text.SimpleDateFormat;
import java.util.Date;
 
public class PeopleB extends Thread{
    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    @Override
    public void run() { //被調用start方法後,就會執行run方法裡的代碼
        System.out.println(this.getName() + " 我準備好回答瞭。");
 
        //使用死循環寫法,讓線程PeopleB永遠不會自動停止運行
        while(true){
            //有人提問,且沒有人回答的情況下,就回答問題
            if(Language.answer == null) {
                String an = answerQuestion(Language.question); //根據問題得到答案
                Language.setAnswer(an);//設置答案
                System.out.println(this.getName() + ":" + an);//打印答案
                Language.question = null;//回答完畢後,把問題設置為空。
            }else{
                System.out.println("請你繼續提問...");
            }
 
            try {
                //隨機休眠0-15秒,模擬用戶B的思考時間
                Thread.sleep(1000 * Language.random.nextInt(15));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
 
    }
 
    //根據問題得到答案
    private String answerQuestion(String question) {
        if(question == null){
            return "請開始提問...";
        }
        String an = "這個問題太難瞭,答不上來。";//默認回答語句
        if(question.equals("你叫什麼名字?")){
            an = this.getName();
        }else if(question.equals("現在幾點瞭?")){
            an = format.format(new Date());
        }else if(question.equals("你早飯吃的什麼?")){
            an = "豆漿油條。";
        }else if(question.equals("你的身高多少?")){
            an = "身高1米85。";
        }else if(question.equals("你最喜歡的Csdn博主是誰?")){
            an = "青00(一起學Java)";
        }else{
 
        }
        return an;
    }
}

 4.創建ThreadTest對象的main函數,啟動2個線程,觀察運行結果(每次結果可能都不一樣):

package com.my.thread;
 
public class ThreadTest {
    public static void main(String[] args) {
        //在mian 線程(主線程)中創建瞭2個子線程 peopleA,peopleB
        PeopleA peopleA = new PeopleA();
        PeopleB peopleB = new PeopleB();
        //給子線程取個名字
        peopleA.setName("提問者");
        peopleB.setName("回答者");
        //啟動peopleA,peopleB線程,啟動後系統將增加一個線程去執行run方法裡的代碼
        peopleA.start();
        peopleB.start();
        //打印這句表示主線程啟動子線程後,會繼續執行後續代碼,不會關心子線程什麼時候執行
        System.out.println("main函數結束瞭。");
    }
}

 5.運行ThreadTest.java,觀察結果,體會多線程的工作原理。

多線程的使用註意事項:有效利用多線程的關鍵是理解程序是並發執行而不是串行執行的。

例如:程序中有兩個子系統需要並發執行,這時候就需要利用多線程編程。通過對多線程的使用,可以編寫出非常高效的程序。

請註意,如果你創建太多的線程,程序執行的效率實際上是降低瞭,而不是提升瞭。請記住,上下文的切換開銷也很重要,如果你創建瞭太多的線程,CPU 花費在上下文的切換的時間將多於執行程序的時間!

 到此這篇關於Java實現模擬機器人對話的示例代碼的文章就介紹到這瞭,更多相關Java 機器人對話內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: