什麼是消息?
何爲消息?消息就是帶有某種信息的信號,如你用鼠標點擊一個窗口會產生鼠標的消息,鍵盤輸入字符會產生鍵盤的消息,一個窗口大小的改變也會產生消息。
消息從何而來?根據馮·諾依曼的體系結構計算機有運算器、存儲器、控制器和輸入設備和輸出設備五大部件組成,消息主要來自輸入設備,如鍵盤、鼠標、掃描儀等,也可來自已窗口和操做系統。
消息機制的三大要點:消息隊列、消息循環(分發)、消息處理。其結構以下:
java
消息隊列就是存放消息的一種隊列,具備先進先出的特色。每產生一個消息都會添加進消息隊列中,在Window中消息隊列是在操做系統中定義的。消息隊列就如同一羣排隊打飯的少男少女,這羣人中光景較好的排在前面,光景較差的排在後面,能夠理解成是一種優先級隊列!要想更多的瞭解隊列的相關知識,可參見隊列。
消息循環就是經過循環(如while)不斷地從消息隊列中取得隊首的消息,並將消息分發出去。相似於上面的例子中分發飯菜值日生。
消息處理就是在接收到消息以後根據不一樣的消息類型作出不一樣的處理。上面例子中值日生根據學生不一樣類型的飯票給他們不一樣等級的飯菜就是消息處理,學生手中的飯票就是消息所攜帶的信息。
事件是根據接收到的消息的具體信息作出的特定的處理,放在代碼中是事件響應函數。上面的例子中學生拿到飯菜後吃飯就是具體的事件。
ide
消息機制模擬
在這裏咱們以控制檯輸入信息模擬窗口、對話框接收鼠標、鍵盤等消息,以ArrayBlockingQueue對象存放消息隊列。在控制檯中輸入一個數值和一個字符串表明一個消息,輸入-1結束輸入。模擬代碼以下:函數
package message; import java.util.Queue; import java.util.Scanner; import java.util.concurrent.ArrayBlockingQueue; /** * 消息 * @author luoweifu */ class Message { //消息類型 public static final int KEY_MSG = 1; public static final int MOUSE_MSG = 2; public static final int SYS_MSG = 3; private Object source; //來源 private int type; //類型 private String info; //信息 public Message(Object source, int type, String info) { super(); this.source = source; this.type = type; this.info = info; } public Object getSource() { return source; } public void setSource(Object source) { this.source = source; } public int getType() { return type; } public void setType(int type) { this.type = type; } public String getInfo() { return info; } public void setInfo(String info) { this.info = info; } public static int getKeyMsg() { return KEY_MSG; } public static int getMouseMsg() { return MOUSE_MSG; } public static int getSysMsg() { return SYS_MSG; } } interface MessageProcess { public void doMessage(Message msg); } /** * 窗口模擬類 */ class WindowSimulator implements MessageProcess{ private ArrayBlockingQueue msgQueue; public WindowSimulator(ArrayBlockingQueue msgQueue) { this.msgQueue = msgQueue; } public void GenerateMsg() { while(true) { Scanner scanner = new Scanner(System.in); int msgType = scanner.nextInt(); if(msgType < 0) { //輸入負數結束循環 break; } String msgInfo = scanner.next(); Message msg = new Message(this, msgType, msgInfo); try { msgQueue.put(msg); //新消息加入到隊尾 } catch (InterruptedException e) { e.printStackTrace(); } } } @Override /** * 消息處理 */ public void doMessage(Message msg) { switch(msg.getType()) { case Message.KEY_MSG: onKeyDown(msg); break; case Message.MOUSE_MSG: onMouseDown(msg); break; default: onSysEvent(msg); } } //鍵盤事件 public static void onKeyDown(Message msg) { System.out.println("鍵盤事件:"); System.out.println("type:" + msg.getType()); System.out.println("info:" + msg.getInfo()); } //鼠標事件 public static void onMouseDown(Message msg) { System.out.println("鼠標事件:"); System.out.println("type:" + msg.getType()); System.out.println("info:" + msg.getInfo()); } //操做系統產生的消息 public static void onSysEvent(Message msg) { System.out.println("系統事件:"); System.out.println("type:" + msg.getType()); System.out.println("info:" + msg.getInfo()); } } /** * 消息模擬 * @author luoweifu */ public class MessageSimulator { //消息隊列 private static ArrayBlockingQueue<Message> messageQueue = new ArrayBlockingQueue<Message>(100); public static void main(String[] args) { WindowSimulator generator = new WindowSimulator(messageQueue); //產生消息 generator.GenerateMsg(); //消息循環 Message msg = null; while((msg = messageQueue.poll()) != null) { ((MessageProcess) msg.getSource()).doMessage(msg); } } }
這裏模擬用例中只有一個消息輸入源,且是一種線程阻塞的,只有輸入結束後纔會進行消息的處理。真實的Windows操做系統中的消息機制會有多個消息輸入源,且消息輸入的同時也能進行消息的處理。this
轉載來源:https://blog.csdn.net/luoweifu/article/details/45568411spa