首頁 > 軟體

Java實現模擬機器人對話的範例程式碼

2022-06-27 18:00:59

前言

今天帶大家來體驗一下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 機器人對話內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com