
PingPong算法非常簡單
如果輪到我{
更新下一輪
ping / pong-記錄點擊
通知其他線程
}其他{
等待通知
}
讓我們來看一個例子,看看它是如何工作的! 這是我們的Player類,它實現Runnable并接受對共享資源和消息的訪問
public class Player implements Runnable {PingPong myTable; Table where they playString myOpponent;public Player(String opponent, PingPong table) {myTable = table;myOpponent = opponent;}public void run() {while (myTable.hit(myOpponent));}}
其次,我們看到PingPong表類,該類具有一個同步方法hit(),無論是否輪到我,都在其中進行檢查。 如果輪到我了,請記錄ping并更新對手姓名的共享變量。
public class PingPong {state variable identifying whose turn it is.private String whoseTurn = null;public synchronized boolean hit(String opponent) {String x = Thread.currentThread().getName();if (x.compareTo(whoseTurn) == 0) {System.out.println('PING! (' + x + ')');whoseTurn = opponent;notifyAll();} else {try { wait(2500); } catch (InterruptedException e) { }}}}
接下來,我們開始游戲并使玩家開始!
public class Game {public static void main(String args[]) {PingPong table = new PingPong();Thread alice = new Thread(new Player('bob', table));Thread bob = new Thread(new Player('alice', table));alice.setName('alice');bob.setName('bob');alice.start(); alice starts playingbob.start(); bob starts playingtry {Wait 5 secondsThread.sleep(5000);} catch (InterruptedException e) {}table.hit('DONE'); cause the players to quit their threads.try {Thread.sleep(100);} catch (InterruptedException e) {}}}
就是這樣,我們正在運行PingPong游戲。 在這種情況下,我們看到了同步方法hit()如何僅允許一個線程訪問共享資源– itsTurn。
Akka STM提供了兩個構造Refs和Agents。 引用(事務引用)提供對多個身份的協調同步訪問。 代理提供對單個身份的非協調異步訪問。
參考
在我們的例子中,由于共享狀態變量是單個標識,因此引用的使用是過大的,但是我們仍然會繼續查看它們的用法。
public class PingPong {updates to Ref.View are synchronousRef.View<String> whoseTurn;public PingPong(Ref.View<String> player) {whoseTurn = player;}public boolean hit(final String opponent) {final String x = Thread.currentThread().getName();if (x.compareTo(whoseTurn.get()) == 0) {System.out.println('PING! (' + x + ')');whoseTurn.set(opponent);} else {try {wait(2500);} catch (Exception e) {}}}}
這里的關鍵是以下
- 同步關鍵字丟失
- 將狀態變量定義為Ref
//更新到Ref.View是同步的
Ref.View <string>其Turn; - 調用更新Ref是協調和同步的
whoTurn.set(opponent) ;
因此,當我們使用Ref保持狀態時,對Ref的訪問會在事務中自動同步。
代理商
由于代理提供了不協調的異步訪問,因此使用代理進行狀態操作將意味著我們需要等到所有更新都已應用到代理之后。 代理為獲取提供非阻塞訪問。
public class PingPong {Agent<String> whoseTurn;public PingPong(Agent<String> player) {whoseTurn = player;}public boolean hit(final String opponent) {final String x = Thread.currentThread().getName();wait till all the messages are processed to make you get the correct value, as updated to Agents areasyncString result = whoseTurn.await(new Timeout(5, SECONDS));if (x.compareTo(result) == 0) {System.out.println('PING! (' + x + ')');whoseTurn.send(opponent);} else {try {wait(2500);} catch (Exception e) {}}return true; keep playing.}}
這里的關鍵是以下
- 同步關鍵字丟失
- 將狀態變量定義為Agent
//更新到Ref.View是同步的
Agent <string>其Turnn; - 等待對代理的更新,因為對代理的更新是異步的
字符串結果= whoTurn.await(new Timeout(5,SECONDS)); - 調用更新Ref是協調和同步的
whoTurn.send(opponent) ;
這些示例中引用的所有代碼都可以在– https://github.com/write2munish/Akka-Essentials/tree/master/AkkaSTMExample/src/main/java/org/akka/essentials/stm/pingpong中找到
示例1 –用于基于普通線程的同步
示例2 –使用Refs進行同步 示例3 –使用代理進行同步
參考:在Akka Essentials博客上,與我們的JCG合作伙伴 Munish K Gupta 一起使用STM – Refs和Agents打乒乓球。
翻譯自: https://www.javacodegeeks.com/2012/05/akka-stm-playing-pingpong-with-stm-refs.html