JAVA《多线程多人上线通知案例》

代理类的两种写法:
package com.wangbiao.mybetty.demo;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class PlayerProxy  implements InvocationHandler {


//    public Object getPlayer(Object target) {
//        return Proxy.newProxyInstance(
//                target.getClass().getClassLoader(),
//                target.getClass().getInterfaces(),
//                // 这里其实是要实现jdk代理InvocationHandler的接口,然后改成JKD8的写法了而已
//                (proxy, method, args) -> {
//                    System.out.println("[JDK动态代理]开着法拉利到小区接你");
//                    // 执行目标对象方法
//                    Object returnValue = method.invoke(target, args);
//                    System.out.println("[JDK动态代理]开着法拉利送你回家");
//                    return returnValue;
//                }
//        );
//    }

    
    
    
    
    //真实对象
    private Object target;

    /**
     * 建立代理对象和真实对象的代理关系方法,并返回代理对象
     * @param target 真实对象
     * @return 代理对象
     */
    public Object bing(Object target){
        this.target = target;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    }

    /**
     *
     * @param proxy 代理对象
     *
     * @param method 当前调度方法
     * @param args 当前方法参数
     * @return 代理结果返回
     * @throws Throwable 异常
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("进入代理逻辑方法");
        System.out.println("在调度真实对象之前的服务");
        Object obj = method.invoke(target, args);//相当于调用sayHello方法

        System.out.println("在调度真实对象后的方法");
        return obj;
    }


}

 

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();
    }
}

 

posted @ 2021-04-19 21:16  余生请多指教ANT  阅读(396)  评论(5编辑  收藏  举报