zoukankan      html  css  js  c++  java
  • JAVA《多线程多人上线通知案例》

    package com.wangbiao.palyermanager;
    
    import com.wangbiao.player.Player;
    
    /**
     * TODO
     *
     * @author wangbiao
     * @Title TODO
     * @module TODO
     * @description 多人在线管理器
     * @date 2021/4/19 13:26
     */
    public interface PlayerManager {
        /**
         * 增加一个玩家对象。
         */
        void addPlayer(Player player) throws InterruptedException;
    
        /**
         * 根据用户名获取玩家对象。
         */
        Player getPlayer(String username);
    
        /**
         * 向系统中的所有玩家广播一条消息。
         */
        void broadcast(String message) throws InterruptedException;
    
    }
    
    package com.wangbiao.player;
    
    /**
     * TODO
     *
     * @author wangbiao
     * @Title TODO
     * @module TODO
     * @description TODO
     * @date 2021/4/19 13:26
     */
    
    /*
    题目:实现Player和PlayerManager接口的功能。
    
    要求:
    1、Player对象以username为索引,且Player对象创建之后,username不会变化。   》容器
    2、PlayerManager中的所有功能是线程安全的,可并发执行。                  多线程
    3、PlayerManager每隔一分钟会将isOffline() == true的Player对象删除。  timetask》可升级为定时器
    4、编写针对PlayerManager功能的单元测试,确保PlayerManager的功能正确。     观察者模式/监听
    */
    
    public interface Player {
        /**
         * 用户名。
         */
         String getUsername();
    
        /**
         * 向玩家发送消息。
         */
        void write(String message);
    
        /**
         * 玩家是否掉线。
         */
        boolean isOffline();
    
    }
    
    package com.wangbiao;
    
    import com.wangbiao.palyermanager.PlayerManager;
    import com.wangbiao.player.Player;
    
    import java.util.Iterator;
    import java.util.Map;
    import java.util.Observable;
    import java.util.concurrent.*;
    import java.util.concurrent.locks.ReentrantLock;
    
    
    /**
     * TODO
     *
     * @author wangbiao
     * @Title TODO
     * @module TODO
     * @description 线程实现
     * @date 2021/4/19 14:45
     */
    public class SunCallable implements Callable<String> {
    private  static ReentrantLock reentrantLock=new ReentrantLock();
        private static final  Object object = new Object();
        private  static  volatile   ConcurrentHashMap<String, Player> hashMap;
    
        private ThreadPoolExecutor taskExecutor;
        private CountDownLatch latch;
        private Player player;
    
        public SunCallable(ThreadPoolExecutor taskExecutor, CountDownLatch latch, Player player,ConcurrentHashMap<String, Player> hashMap) {
            this.latch = latch;
            this.taskExecutor = taskExecutor;
            this.player = player;
            this.hashMap=hashMap;
        }
    
        public  String call() throws Exception {
    
                try {
                    SunCallable.PlayerManagerInstance playerManagerInstance=new PlayerManagerInstance();
                    Thread.sleep(1000);
                    playerManagerInstance.addPlayer(this.player);
                    Thread.sleep(1000);
                    playerManagerInstance.broadcast("管理器通知:昵称为《" + this.player.getUsername() + "》上线了");
                } finally {
                    latch.countDown();
                }
    
            return "ok";
        }
    
    //静态内部类
      static   class PlayerManagerInstance extends Observable implements PlayerManager {
            public synchronized   void addPlayer(Player player) throws InterruptedException {
                    hashMap.put(player.getUsername(), player);
                    System.out.println("管理器通知:昵称为《" + player.getUsername() + "》上线了");
                    setChanged();
                    notifyObservers(player);
    
    
    
            }
    
            public Player getPlayer(String username) {
                    return hashMap.get(username);
    
            }
    
            /**
             * 向系统中的所有玩家广播一条消息。
             */
            public  synchronized   void broadcast(String message) throws InterruptedException {
                    for (Iterator<Map.Entry<String, Player>> iterator = hashMap.entrySet().iterator(); iterator.hasNext(); ) {
    
                        Map.Entry<String, Player> next = iterator.next();
                        Player player = next.getValue();
    //                    if (getPlayer(player.getUsername()) == player) {
    //                        continue;
    //                    }
                        Thread.sleep(1000);
                        player.write(message);
                    }
    
            }
        }
    }
    
    package com.wangbiao;
    
    import com.wangbiao.player.Player;
    import com.wangbiao.player.Player1;
    import com.wangbiao.player.PlayerProxy;
    import jdk.nashorn.internal.parser.JSONParser;
    import netscape.javascript.JSObject;
    
    import java.util.Timer;
    import java.util.concurrent.*;
    
    /**
     * TODO
     *
     * @author wangbiao
     * @Title TODO
     * @module TODO
     * @description TODO
     * @date 2021/4/19 13:46
     */
    public class PayerTest {
        private  static  volatile ConcurrentHashMap<String, Player> hashMap = new ConcurrentHashMap();
    
        public static void main(String[] args) throws InterruptedException {
    
            ThreadPoolExecutor taskExecutor = new ThreadPoolExecutor(500,1000,3000, TimeUnit.MINUTES,   new LinkedBlockingQueue<Runnable>());
            CountDownLatch latch = new CountDownLatch(10);
            PlayerProxy playerProxy=new PlayerProxy();
            for (int i = 1; i <=10 ; i++) {
    //动态代理类在多线程高并发场景下,出现只有一个线程实力有效的情况,所以一个玩家还是一个线程任务比较安全
    //            Player player=playerProxy.getPlayer(new Player1("玩家"+i));  //巨坑卡了我一个下午
                Player1 player1 = new Player1("玩家" + i);
                taskExecutor.submit(new SunCallable(taskExecutor,latch,player1,hashMap));
            }
            MyTimeTask myTimeTask = new MyTimeTask(hashMap);
            Timer myTimer=new Timer();
            myTimer.schedule(myTimeTask,6000,6000);
            latch.await(1,TimeUnit.MINUTES);
            taskExecutor.shutdown();
        }
    }
    
    一点点学习,一丝丝进步。不懈怠,才不会被时代淘汰
  • 相关阅读:
    【GO】GO开发环境安装及VS Code配置
    【计算机组成原理】第一章 计算机系统概论
    oracle 12.2新特性:sqlplus history
    取消交互式创建linux用户密码
    undo表空间收缩
    如何对undo表空间大小进行设置
    查看数据库实际使用多大内存
    Oracle 12.2Cgrid脚本安装失败软件完全删除
    有关rman备份ora-27192和ora-19511错误
    数据库altert日志中的GTX提示
  • 原文地址:https://www.cnblogs.com/wangbiaohistory/p/14678719.html
Copyright © 2011-2022 走看看