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!