多进程调用共享资源
来源:互联网 发布:淘宝哎呦喂被挤爆了 编辑:程序博客网 时间:2024/06/13 15:04
本文主要参考Lamport算法,是对多进程调用共享资源算法的一个具体实现.业务场景为分布式中,使用dubbo调用后台某个服务,该服务部署有多个,服务中有对hdfs写的操作,要知道hdfs每次只支持一个客户端去写,所以这就是个多进程互斥访问共有资源的问题.下面是主要实现代码,具体业务可根据使用场景做调整:
public class WriteHDFS { //本地用一个LinkedHashMap做时间戳存储 private static TreeMap<Long, String> queue = new TreeMap<Long, String>(); //每个服务初始化序号为0 private static long num = 0; //最长心跳间隔 private static int MAX_TIME = 10000; private static Date time1 = null; private static Date time2 = null; static Consumer statToHdfs = null; public static void WriteHdfs(StatService statService, UserService userService) throws Exception { //服务所在主机地址 String local = InetAddress.getLocalHost().getHostAddress(); InetAddress ip = InetAddress.getByName("255.255.255.255"); DatagramSocket sendDs = new DatagramSocket(); //将本地序号,ip封装后广播发送 HashMap<Long, String> sendMap = new HashMap<Long, String>(); /** * 接收广播线程,更新序号 */ new Thread(new Runnable(){ @Override public void run() { //接收广播,将序号更新 DatagramSocket recvDs = null; try { recvDs = new DatagramSocket(8888); byte[] buf = new byte[1024]; DatagramPacket recvDp = new DatagramPacket(buf, buf.length); recvDs.receive(recvDp); String revStr = recvDp.getData().toString(); JSONObject data = JSONObject.parseObject(revStr); if (data.containsKey("startData") || data.containsKey("endData")) { @SuppressWarnings("unchecked") HashMap<Integer, String> revMap = (HashMap<Integer, String>) data.get("startData"); //遍历revMap,并放入本地队列 for(Integer key:revMap.keySet()) { if (num <= key) num = key; } } } catch (Exception e) { e.printStackTrace(); } finally { recvDs.close(); } } }).start(); /** * 发送广播线程,更新队列 */ new Thread(new Runnable(){ @Override public void run() { //DatagramSocket sendDs = null; //当要获取资源时,序号自增1,并广播通知其他服务 try { num++; sendMap.put(num, local); JSONObject startObj = new JSONObject(); startObj.put("startData", sendMap); String startStr = startObj.toJSONString(); DatagramPacket sendDp = new DatagramPacket(startStr.getBytes(),startStr.getBytes().length, ip, 8888); sendDs.send(sendDp); } catch (Exception e) { e.printStackTrace(); } } }).start(); /** * 接收广播,更新队列判断是否可以获取资源 */ new Thread(new Runnable() { @Override public void run() { //接收广播,并比较key-value,直到获取资源 while(true) { //比较queue中最小key和此时num,以及主机ip,如果相同则表示可以获得资源 if (queue.firstKey() == num && queue.get(queue.firstKey()) == local) { // 开启将数据周期写入Hdfs线程 //此处为写hdfs业务逻辑,已省略xxxxxxx //queue移除首元素 queue.remove(queue.firstKey()); //资源释放,广播通知其他服务 JSONObject endObj = new JSONObject(); endObj.put("endData", sendMap); String endStr = endObj.toJSONString(); DatagramPacket freeDp = new DatagramPacket(endStr.getBytes(),endStr.getBytes().length, ip, 8888); try { sendDs.send(freeDp); } catch (Exception e) { e.printStackTrace(); } sendDs.close(); break; } DatagramSocket ds = null; try { ds = new DatagramSocket(8888); } catch (Exception e) { e.printStackTrace(); } byte[] bf = new byte[1024]; DatagramPacket dp = new DatagramPacket(bf, bf.length); try { ds.receive(dp); } catch (Exception e) { e.printStackTrace(); } String str = dp.getData().toString(); JSONObject obj = JSONObject.parseObject(str); if (obj.containsKey("startData")) { @SuppressWarnings("unchecked") HashMap<Long, String> revMap = (HashMap<Long, String>) obj.get("startData"); //遍历revMap,并放入本地队列 for(Long key:revMap.keySet()) { if (!queue.containsKey(key)) { queue.put(key, revMap.get(key)); //建立和正在使用资源服务的心跳连接,如果挂掉就从队列删除key-value Timer timer = new Timer(); timer.scheduleAtFixedRate(new TimerTask() { @Override public void run() { //向正在使用资源的服务发送心跳包 try { @SuppressWarnings("resource") DatagramSocket reqSocket = new DatagramSocket(); JSONObject reqObj = new JSONObject(); reqObj.put("requestData", local); String reqStr = reqObj.toJSONString(); DatagramPacket reqDp = new DatagramPacket(reqStr.getBytes(), reqStr.getBytes().length, new InetSocketAddress(revMap.get(key), 8888)); reqSocket.send(reqDp); time1 = new Date(); } catch (Exception e) { e.printStackTrace(); } } }, 1000, 3000); if(time1 != null && time2 != null && Math.abs(time1.getTime() - time2.getTime())/1000 > MAX_TIME) { queue.remove(key); } } } } if (obj.containsKey("requestData")) { String reqHost = (String) obj.get("requestData"); try { @SuppressWarnings("resource") DatagramSocket repSocket = new DatagramSocket(); JSONObject repObj = new JSONObject(); repObj.put("reponseData", local); String repStr = repObj.toJSONString(); DatagramPacket repDp = new DatagramPacket(repStr.getBytes(), repStr.getBytes().length, new InetSocketAddress(reqHost, 8888)); repSocket.send(repDp); } catch (Exception e) { e.printStackTrace(); } } if (obj.containsKey("reponseData")) { time2 = new Date(); } if (obj.containsKey("endData")) { @SuppressWarnings("unchecked") HashMap<Long, String> revMap = (HashMap<Long, String>) obj.get("endData"); //遍历revMap,从本地队列删除对应key-value for(Long key:revMap.keySet()) { if (queue.containsKey(key)) queue.remove(key); } } } } }).start(); } }
需要用三个线程实现,主要原因是接受广播的方法是阻塞的.一个线程用来发送广播,一个用来接收广播,最后一个用来判断本地队列是否获取资源,如果为否则继续接收广播更新队列;队列用TreeMap顺序存储,如果获取资源的服务挂掉则可以通过心跳判断来更新本地队列;
阅读全文
0 0
- 多进程调用共享资源
- 多进程之间的共享资源互斥
- linux下多进程共享资源互斥访问实例
- 同一进程中线程共享资源
- 共享进程id,sharedpreferences 共享资源
- fork后父子进程共享资源
- 共享资源
- 共享资源
- 共享资源
- Linux下的多进程间共享资源的互斥访问
- Linux下的多进程间共享资源的互斥访问
- Linux下的多进程间共享资源的互斥访问
- 同一进程间的线程共享资源
- 多进程调用winrar
- 同一进程中线程的共享资源以及独有资源
- 进程间 对共享资源的访问 互斥 机制
- 12-进程间通信-信号量(功能:共享资源)
- 如何判断多个线程是否共享资源
- Ubuntu系统如何安装VMware tools
- Spring+redis缓存使用
- 关于loadrunner测试接口的问题
- lightoj 1245 Harmonic Number (II)
- 学习笔记1-C++-strcat,strcpy函数
- 多进程调用共享资源
- 基于maven发送邮件系列(5)----基于quartz定时的另一种方式:配置文件
- swift3.0 语法
- 线程基本概念
- UniqueService(解决事务时获取服务地址后直接使用)
- 剑指offer-14:调整数组顺序,奇数位于偶数前面
- javascript高级程序设计第三版 第8章 BOM
- 常见错误
- JZOJ 5264. 【NOIP2017模拟8.12A组】化学