「java消息广播」java电台

博主:adminadmin 2022-12-15 20:03:09 78

今天给各位分享java消息广播的知识,其中也会对java电台进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!

本文目录一览:

java里怎么发广播呀

java里怎么发广播

public void onReceive(Context context,Intent intent){

Intent intent = new Intent(context,XxxService.class);

context.startService(intent);

}

Intent intent = new Intent();

intent.setAction("...");

Context.sendBroadcast(intent);

"Java"的中文意思是什么?

Java名词解释

Abstract class 抽象类:抽象类是不允许实例化的类,因此一般它需要被进行扩展继承。

Abstract method 抽象方法:抽象方法即不包含任何功能代码的方法。

Access modifier 访问控制修饰符:访问控制修饰符用来修饰Java中类、以及类的方法和变量的访问控制属性。

Anonymous class 匿名类:当你需要创建和使用一个类,而又不需要给出它的名字或者再次使用的使用,就可以利用匿名类。

Anonymous inner classes 匿名内部类:匿名内部类是没有类名的局部内部类。

API 应用程序接口:提供特定功能的一组相关的类和方法的集合。

Array 数组:存储一个或者多个相同数据类型的数据结构,使用下标来访问。在Java中作为对象处理。

Automatic variables 自动变量:也称为方法局部变量method local variables,即声明在方法体中的变量。

AWT抽象窗口工具集:一个独立的API平台提供用户界面功能。

Base class 基类:即被扩展继承的类。

Blocked state 阻塞状态:当一个线程等待资源的时候即处于阻塞状态。阻塞状态不使用处理器资源

Call stack 调用堆栈:调用堆栈是一个方法列表,按调用顺序保存所有在运行期被调用的方法。

Casting 类型转换 :即一个类型到另一个类型的转换,可以是基本数据类型的转换,也可以是对象类型的转换。

char 字符:容纳单字符的一种基本数据类型。

Child class 子类:见继承类Derived class

Class 类:面向对象中的最基本、最重要的定义类型。

Class members 类成员:定义在类一级的变量,包括实例变量和静态变量。

Class methods 类方法:类方法通常是指的静态方法,即不需要实例化类就可以直接访问使用的方法。

Class variable 类变量:见静态变量Static variable

Collection 容器类:容器类可以看作是一种可以储存其他对象的对象,常见的容器类有Hashtables和Vectors。

Collection interface 容器类接口:容器类接口定义了一个对所有容器类的公共接口。

Collections framework 容器类构架:接口、实现和算法三个元素构成了容器类的架构。

Constructor 构造函数:在对象创建或者实例化时候被调用的方法。通常使用该方法来初始化数据成员和所需资源。

Containers容器:容器是一种特殊的组件,它可以容纳其他组件。

Declaration 声明:声明即是在源文件中描述类、接口、方法、包或者变量的语法。

Derived class 继承类:继承类是扩展继承某个类的类。

Encapsulation 封装性:封装性体现了面向对象程序设计的一个特性,将方法和数据组织在一起,隐藏其具体实现而对外体现出公共的接口。

Event classes 事件类:所有的事件类都定义在java.awt.event包中。

Event sources 事件源:产生事件的组件或对象称为事件源。事件源产生事件并把它传递给事件监听器event listeners。

Exception 异常:异常在Java中有两方面的意思。首先,异常是一种对象类型。其次,异常还指的是应用中发生的一种非标准流程情况,即异常状态。

Extensibility扩展性:扩展性指的是面向对象程序中,不需要重写代码和重新设计,能容易的增强源设计的功能。

Finalizer 收尾:每个类都有一个特殊的方法finalizer,它不能被直接调用,而被JVM在适当的时候调用,通常用来处理一些清理资源的工作,因此称为收尾机制。

Garbage collection 垃圾回收机制:当需要分配的内存空间不再使用的时候,JVM将调用垃圾回收机制来回收内存空间。

Guarded region 监控区域:一段用来监控错误产生的代码。

Heap堆:Java中管理内存的结构称作堆。

Identifiers 标识符:即指定类、方法、变量的名字。注意Java是大小写敏感的语言。

Import statement 引入语法:引入语法允许你可以不使用某个类的全名就可以参考这个类。

Inheritance 继承:继承是面向对象程序设计的重要特点,它是一种处理方法,通过这一方法,一个对象可以获得另一个对象的特征。

Inner classes 内部类:内部类与一般的类相似,只是它被声明在类的内部,或者甚至某个类方法体中。

Instance 实例:类实例化以后成为一个对象。

Instance variable 实例变量:实例变量定义在对象一级,它可以被类中的任何方法或者其他类的中方法访问,但是不能被静态方法访问。

Interface 接口:接口定义的是一组方法或者一个公共接口,它必须通过类来实现。

Java source file Java源文件:Java源程序包含的是Java程序语言计算机指令。

Java Virtual Machine (JVM) Java虚拟机:解释和执行Java字节码的程序,其中Java字节码由Java编译器生成。

javac Java编译器:Javac是Java编译程序的名称。

JVM Java虚拟机:见Java虚拟机

Keywords 关键字:即Java中的保留字,不能用作其他的标识符。

Layout managers 布局管理器:布局管理器是一些用来负责处理容器中的组件布局排列的类。

Local inner classes 局部内部类:在方法体中,或者甚至更小的语句块中定义的内部类。

Local variable 局部变量:在方法体中声明的变量

Member inner classes 成员内部类:定义在封装类中的没有指定static修饰符的内部类。

Members 成员:类中的元素,包括方法和变量。

Method 方法:完成特定功能的一段源代码,可以传递参数和返回结果,定义在类中。

Method local variables 方法局部变量:见自动变量Automatic variables

Modifier 修饰符:用来修饰类、方法或者变量行为的关键字。

Native methods 本地方法:本地方法是指使用依赖平台的语言编写的方法,它用来完成Java无法处理的某些依赖于平台的功能。

Object 对象:一旦类实例化之后就成为对象。

Overloaded methods 名称重载方法:方法的名称重载是指同一个类中具有多个方法,使用相同的名称而只是其参数列表不同。

Overridden methods 覆盖重载方法:方法的覆盖重载是指父类和子类使用的方法采用同样的名称、参数列表和返回类型。

Package 包:包即是将一些类聚集在一起的一个实体。

Parent class 父类:被其他类继承的类。也见基类。

Private members 私有成员:私有成员只能在当前类被访问,其他任何类都不可以访问之。

Public members 公共成员:公共成员可以被任何类访问,而不管该类属于那个包。

Runtime exceptions 运行时间异常:运行时间异常是一种不能被你自己的程序处理的异常。通常用来指示程序BUG。

Source file 源文件:源文件是包含你的Java代码的一个纯文本文件。

Stack trace 堆栈轨迹:如果你需要打印出某个时间的调用堆栈状态,你将产生一个堆栈轨迹。

Static inner classes 静态内部类:静态内部类是内部类最简单的形式,它于一般的类很相似,除了被定义在了某个类的内部。

Static methods 静态方法:静态方法声明一个方法属于整个类,即它可以不需要实例化一个类就可以通过类直接访问之。

Static variable 静态变量:也可以称作类变量。它类似于静态方法,也是可以不需要实例化类就可以通过类直接访问。

Superclass 超类:被一个或多个类继承的类。

Synchronized methods 同步方法:同步方法是指明某个方法在某个时刻只能由一个线程访问。

Thread 线程:线程是一个程序内部的顺序控制流。

Time-slicing 时间片:调度安排线程执行的一种方案。

Variable access 变量访问控制:变量访问控制是指某个类读或者改变一个其他类中的变量的能力。

Visibility 可见性: 可见性体现了方法和实例变量对其他类和包的访问控制。

容器:充当中间件的角色

WEB容器:给处于其中的应用程序组件(JSP,SERVLET)提供一个环境,使JSP,SERVLET直接更容器中的环境变量接口交互,不必关注其它系统问题。主要有WEB服务器来实现。例如:TOMCAT,WEBLOGIC,WEBSPHERE等。该容器提供的接口严格遵守J2EE规范中的WEB APPLICATION 标准。我们把遵守以上标准的WEB服务器就叫做J2EE中的WEB容器。

EJB容器:Enterprise java bean 容器。更具有行业领域特色。他提供给运行在其中的组件EJB各种管理功能。只要满足J2EE规范的EJB放入该容器,马上就会被容器进行高效率的管理。并且可以通过现成的接口来获得系统级别的服务。例如邮件服务、事务管理。

WEB容器和EJB容器在原理上是大体相同的,更多的区别是被隔离的外界环境。WEB容器更多的是跟基于HTTP的请求打交道。而EJB容器不是。它是更多的跟数据库、其它服务打交道。但他们都是把与外界的交互实现从而减轻应用程序的负担。例如SERVLET不用关心HTTP的细节,直接引用环境变量session,request,response就行、EJB不用关心数据库连接速度、各种事务控制,直接由容器来完成。

RMI/IIOP:远程方法调用/internet对象请求中介协议,他们主要用于通过远程调用服务。例如,远程有一台计算机上运行一个程序,它提供股票分析服务,我们可以在本地计算机上实现对其直接调用。当然这是要通过一定的规范才能在异构的系统之间进行通信。RMI是JAVA特有的。

JNDI:JAVA命名目录服务。主要提供的功能是:提供一个目录系统,让其它各地的应用程序在其上面留下自己的索引,从而满足快速查找和定位分布式应用程序的功能。

JMS:JAVA消息服务。主要实现各个应用程序之间的通讯。包括点对点和广播。

JAVAMAIL:JAVA邮件服务。提供邮件的存储、传输功能。他是JAVA编程中实现邮件功能的核心。相当MS中的EXCHANGE开发包。

JTA:JAVA事务服务。提供各种分布式事务服务。应用程序只需调用其提供的接口即可。

JAF:JAVA安全认证框架。提供一些安全控制方面的框架。让开发者通过各种部署和自定义实现自己的个性安全控制策略。

EAI:企业应用集成。是一种概念,从而牵涉到好多技术。J2EE技术是一种很好的集成实现。

如何在APP内监听键盘输入消息

1.在lichee/linux-3.0/include/linux/input.h文件可以查看底层驱动的按键编码

#define KEY_F1 59

#define KEY_F2 60

#define KEY_F3 61

#define KEY_F4 62

#define KEY_F5 63

#define KEY_F6 64

#define KEY_F7 65

#define KEY_F8 66

#define KEY_F9 67

#define KEY_F10 68

2.在android4.0/frameworks/base/core/java/android/view/KeyEvent.java文件可以查看上层驱动的按键编码

/** Key code constant: F1 key. */

public static final int KEYCODE_F1 = 131;

/** Key code constant: F2 key. */

public static final int KEYCODE_F2 = 132;

/** Key code constant: F3 key. */

public static final int KEYCODE_F3 = 133;

/** Key code constant: F4 key. */

public static final int KEYCODE_F4 = 134;

/** Key code constant: F5 key. */

public static final int KEYCODE_F5 = 135;

/** Key code constant: F6 key. */

public static final int KEYCODE_F6 = 136;

/** Key code constant: F7 key. */

public static final int KEYCODE_F7 = 137;

/** Key code constant: F8 key. */

public static final int KEYCODE_F8 = 138;

/** Key code constant: F9 key. */

public static final int KEYCODE_F9 = 139;

/** Key code constant: F10 key. */

public static final int KEYCODE_F10 = 140;

3.在/android4.0/frameworks/base/data/keyboards/Generic.kl文件里面有底层到上层的映射,将这个文件定制到自己的系统android4.0/out/target/product/crane-m1003h6/system/usr/keylayout目录下就可以了在上层收到USB键盘F1-F10的消息了。

key 59 F1

key 60 F2

key 61 F3

key 62 F4

key 63 F5

key 64 F6

key 65 F7

key 66 F8

key 67 F9

key 68 F10

4.在/android4.0/frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindow.java文件的onKeyDown,onKeyUp函数截获F1-F10的消息,用自己定义的广播消息广播出去应用就可以在后台或者前台都可以接收到按键按下或者释放的广播消息了。

case KeyEvent.KEYCODE_F1: {

//Log.e("zkliu","---------------------------test F1---------------------------");

getContext().sendBroadcast(new Intent("com.android.action.F1_KEYDOWN"));

return true;

}

case KeyEvent.KEYCODE_F2: {

//Log.e("zkliu","---------------------------test F2---------------------------");

getContext().sendBroadcast(new Intent("com.android.action.F2_KEYDOWN"));

return true;

}

case KeyEvent.KEYCODE_F3: {

//Log.e("zkliu","---------------------------test F3---------------------------");

getContext().sendBroadcast(new Intent("com.android.action.F3_KEYDOWN"));

return true;

}

case KeyEvent.KEYCODE_F4: {

//Log.e("zkliu","---------------------------test F4---------------------------");

getContext().sendBroadcast(new Intent("com.android.action.F4_KEYDOWN"));

return true;

}

case KeyEvent.KEYCODE_F5: {

//Log.e("zkliu","---------------------------test F5---------------------------");

getContext().sendBroadcast(new Intent("com.android.action.F5_KEYDOWN"));

return true;

}

case KeyEvent.KEYCODE_F6: {

//Log.e("zkliu","---------------------------test F6---------------------------");

getContext().sendBroadcast(new Intent("com.android.action.F6_KEYDOWN"));

return true;

}

case KeyEvent.KEYCODE_F7: {

//Log.e("zkliu","---------------------------test F7---------------------------");

getContext().sendBroadcast(new Intent("com.android.action.F7_KEYDOWN"));

return true;

}

case KeyEvent.KEYCODE_F8: {

//Log.e("zkliu","---------------------------test F8---------------------------");

getContext().sendBroadcast(new Intent("com.android.action.F8_KEYDOWN"));

return true;

}

case KeyEvent.KEYCODE_F9: {

//Log.e("zkliu","---------------------------test F9---------------------------");

getContext().sendBroadcast(new Intent("com.android.action.F9_KEYDOWN"));

return true;

}

case KeyEvent.KEYCODE_F10: {

//Log.e("zkliu","---------------------------test F10---------------------------");

getContext().sendBroadcast(new Intent("com.android.action.F10_KEYDOWN"));

return true;

}

case KeyEvent.KEYCODE_F1: {

//Log.e("zkliu","---------------------------test F1---------------------------");

getContext().sendBroadcast(new Intent("com.android.action.F1_KEYUP"));

return true;

}

case KeyEvent.KEYCODE_F2: {

//Log.e("zkliu","---------------------------test F2---------------------------");

getContext().sendBroadcast(new Intent("com.android.action.F2_KEYUP"));

return true;

}

case KeyEvent.KEYCODE_F3: {

//Log.e("zkliu","---------------------------test F3---------------------------");

getContext().sendBroadcast(new Intent("com.android.action.F3_KEYUP"));

return true;

}

case KeyEvent.KEYCODE_F4: {

//Log.e("zkliu","---------------------------test F4---------------------------");

getContext().sendBroadcast(new Intent("com.android.action.F4_KEYUP"));

return true;

}

case KeyEvent.KEYCODE_F5: {

//Log.e("zkliu","---------------------------test F5---------------------------");

getContext().sendBroadcast(new Intent("com.android.action.F5_KEYUP"));

return true;

}

case KeyEvent.KEYCODE_F6: {

//Log.e("zkliu","---------------------------test F6---------------------------");

getContext().sendBroadcast(new Intent("com.android.action.F6_KEYUP"));

return true;

}

case KeyEvent.KEYCODE_F7: {

//Log.e("zkliu","---------------------------test F7---------------------------");

getContext().sendBroadcast(new Intent("com.android.action.F7_KEYUP"));

return true;

}

case KeyEvent.KEYCODE_F8: {

//Log.e("zkliu","---------------------------test F8---------------------------");

getContext().sendBroadcast(new Intent("com.android.action.F8_KEYUP"));

return true;

}

case KeyEvent.KEYCODE_F9: {

//Log.e("zkliu","---------------------------test F9---------------------------");

getContext().sendBroadcast(new Intent("com.android.action.F9_KEYUP"));

return true;

}

case KeyEvent.KEYCODE_F10: {

//Log.e("zkliu","---------------------------test F10---------------------------");

getContext().sendBroadcast(new Intent("com.android.action.F10_KEYUP"));

return true;

}

应用程序注册接收相应的广播消息即可接收到键盘输入消息。

消息队列概念

消息本质上是一种数据结构(当然,对象也可以看做是一种特殊的消息),它包含消费者与服务双方都能识别的数据,这些数据需要在不同的进程(机器)之间进行传递,并可能会被多个完全不同的客户端消费

队列(Queue) ,是先进先出(FIFO, First-In-First-Out)的线性表,通俗的讲队列就是一群人或者事物按照排好的顺序等待接受服务或者处理

本地队列按照功能可划分为初始化队列,传输队列,目标队列和死信队列。初始化队列用作消息触发功能。传输队列只是暂存待传的消息,条件许可的情况下,通过管道将消息传送到其他的队列管理器。目标队列是消息的目的地,可以长期存放消息。如果消息不能送达目标队列,也不能再路由出去,则被自动放入死信队列保存。

只是一个队列定义,用来指定远端队列管理器的队列。使用了远程队列,程序就不需要知道目标队列的位置。

模型队列定义了一套本地队列的属性结合,一旦打开模型队列,队列管理器会按照这些属性动态地创建出一个本地队列。

MQ全称(Message Queue)又名 消息队列 ,是一种 异步通讯 的 中间件 。可以将它理解成邮局,发送者将消息传递到邮局,然后由邮局帮我们发送给具体的消息接收者(消费者),具体发送过程与时间我们无需关心,它也不会干扰我进行其它事情。

它被广泛的应用与跨平台、跨系统的分布式系统之间,为它们提供高效可靠的异步传输机制

JMS(JAVA Message Service,java消息服务)是java的消息服务 JMS是一套 API,是j2EE标准的一部分。

JMS是由Sun公司早期提出的消息标准,旨在为java应用提供统一的消息操作,包括create、send、receive等

JMS是Java Enterprise Edition的一部分。从使用角度看,JMS和JDBC担任差不多的角色,用户都是根据相应的接口可以和实现了JMS的服务进行通信,进行相关的操作

结构图

说明

使用 队列(Queue) 作为消息通信载体;满足 生产者与消费者模式 ,一条消息只能被一个消费者使用,未被消费的消息在队列中保留直到被消费或超时。比如:我们生产者发送100条消息的话,两个消费者来消费一般情况下两个消费者会按照消息发送的顺序各自消费一半(也就是你一个我一个的消费。)

结构图

说明

发布订阅模型(Pub/Sub) 使用 主题(Topic) 作为消息通信载体,类似于 广播模式 ;发布者发布一条消息,该消息通过主题传递给所有的订阅者, 在一条消息广播之后才订阅的用户则是收不到该条消息的 。

AMQP(advanced message queuing protocol) 是一个提供统一消息服务的应用层标准协议,基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,可以跨语法开发

AMQP是一种协议,更准确的说是一种binary wire-level protocol(链接协议),兼容JMS

java游戏服务器开发有前途吗

最近刚跳槽,到新公司已经干了有两周时间了,这两周时间是过得比较充实的,因为这家新公司是个小公司,以前以单机开发为主,服务器方面我一个人,做两个游戏的服务器开发工作,当然,一个很简单,另一个就相对复杂点,简单的那个是个弱联网游戏,服务器只需要做好数据存档和登录支付验证就好了,而另一个,则是相对复杂的slg游戏,我感觉这是又一款cok,而公司目前并不打算再招服务器了,所以估计这个项目我会一个人干到明年吧,等第一款上线赚钱了,可能会再招服务器。老实说,面试的时候,我就觉得这份工作对我而言是一个挑战,而当我清楚的了解了公司状况之后,我依然决定接受这个挑战。

说说我之前的经历吧,大四的时候,学校安排来北京培训java(培训没什么丢脸的,出来找工作我也用的真学历真背景,不像某峰互联),之后我去了培训机构推荐的公司实习,那个时候,工资2k,然而工作也干得很开心,跟着前辈学到了不少东西,当时是做微信公众号开发的,我跟着前辈做微信后台开发,当时使用SpringMVC+MyBatis框架,刚接触的时候,我自己学了挺久才弄明白,后来弄明白之后想想,其实挺简单,对于逻辑开发的程序员来说,你只需要弄懂工作流程就好了,页面怎么跳转,跳转怎么传值,数据怎么处理,这些足够了,当然我是个不满足的人,我会去弄明白,为什么用这个框架、为什么不用别的、用这个有什么好处、如果让我自己来做这个后台、我会怎么搭建?带着这些问题,我会试着自己搭建一下后台框架(虽然前期大部分是复制粘贴)。除了框架部分,微信高级接口也是我研究的重点,我会去官方文档看看微信是怎么接入的,然后研究研究前辈的代码是怎么写的,所谓的干一行爱一行大概就是这样吧,当时我觉得,微信开发,是很有前途的,而我们公司用的框架,也是最先进的(后来看来,确实这个框架组合是当前最流行的框架,而当时,微信公众号也确实是当时互联网行业的一个风口,微信后来把h5带起来了,导致现在一个好的h5前端都是供不应求的,薪资很高)。

说了这么多,为什么后来又转行做游戏了呢?其实是这样的,当时在第一家公司,我的上级打算跳槽走了,带走整个下面的技术,而不带实习生,有那么一两个月,实习生就一直闲着没事做,对于我来说,这样过着就太无聊了,我喜欢挑战,于是我投简历,重新找了份实习工作,在一个游戏公司做java服务器开发,公司挺大的,几年前凭借一款slg页游称霸游戏行业(什么游戏我就不说了,说了就知道什么公司了),后来游戏行业往手游发展,这款slg也出了手游版,这一款游戏,几乎支撑了整个公司,再加上后来出的几款手游,公司发展挺好的,我所实习的部门做的是一款mmorpg手游,从实习做到了转正,做了近一年了,然而这款rpg手游的数据却不是太好,第一次封测次日留存23,第二次26(现在这家公司的游戏能达到80多次日留存),七日就更不用说了,而我也能感觉到,作为一款mmo游戏,玩家之间的交互实在太少,从头玩下来,我觉得这是一款单机,失去了mmo的本质,在项目组准备进行第三次封测的时候,我选择了离开,原因很多,不仅仅因为游戏数据不好,也有一些个人原因吧,不过说实话,是这家公司带我走进了游戏行业,我很感谢,我觉得游戏行业是一个非常有前景的行业,甚至比之前我认为最好的微信开发还要好,游戏行业非常暴利,在这家公司工作就能感受到,策划文档中,充满了挖坑预留的计费点,这一块可以正常玩儿,但你如果充钱,你就比别人牛逼。网络游戏,最重要的,就是控制好平民玩家跟普通玩家的占比以及游戏平衡(当意识到公司的游戏如此处心积虑想要坑钱的时候,我突然明白为什么公司的游戏大多被腾讯代理了,为什么腾讯控股,原来如此,没钱玩儿你**,哈哈)。由此也可以看出,游戏的商业化,已经把游戏公司带入了一个固定的模式——无条件坑钱,我觉得已经失去了游戏的本质,我看过一本书,叫《游戏人生》(当时在cocos2014年开发者大会上买的。觉得挺值的),书已经送人了,但内容我看了一大半,从游戏的产生,到玩家的心理,到为什么需要游戏,这本书都诠释的热别好(我觉得游戏策划都应该看看这本书,做良心游戏,拒绝一味坑钱)。啊,突然发现这一段说的有点偏了,说到底,我也只是做游戏服务器开发的,我也改变不了游戏行业,我只要做好我做的。其实大的游戏公司,就应该走这种商业化路线,凭借几款长生命周期的游戏,支撑公司流水。

从转行做游戏之后,我倒是觉得,游戏开发比web开发有趣多了,当然技术上也比web难多了,之前发过一篇讨论,web开发何和游戏开发的区别,,我把我的答案再粘贴一遍(实际上是别人要求我上他的号去回答的,于是我就自己回答了我自己的问题):

1.从第三方支持来说,web后台有很多成熟的第三方框架,开发者不需要关心底层控制器跳转的实现,只需要一个或几个配置文件,就能完成核心控制器的部分,而开发者只需要关注web自身的业务逻辑,将逻辑与框架融合即可,使用框架一方面简化控制层代码,一方面很好的实现了业务逻辑的分层。而游戏后台开发中,因为各种游戏的需求差异性很大,从网络层,到业务逻辑层,各方面都必须根据自己游戏需求搭建适合自己的框架,因此很难有一些通用的东西能提炼出来一款成熟的框架,游戏后台开发基本上需要自己搭建适合自己的框架。

2.从业务逻辑层面来说,web后台基本上逻辑都是大同小异的,或许这一套系统,稍微改改,另一套系统就能用,而游戏就不同了,每个游戏都有自己的特色,根据策划的不同需求而实现不同的逻辑,不过也会有一些通用的模块,但整体上差异性还是很大的。

3.从数据持久化来说,web的数据基本上是很规整的,表与表之间关系很明确,并且以后也不会有太大的变化,而游戏中的数据多种多样,随着开服之后,数据的变化也是多种多样,甚至传统的关系型数据库根本无法满足游戏数据持久化的需求,游戏中有很多状态和数据是需要服务器来保存的,我个人认为,在游戏开发中,nosql比关系型数据库更实用。

4.从通信层来说,web中的用户都是一个个独立的个体,而游戏中是多人在线的一个游戏世界,在这个游戏世界中,玩家与玩家之间需要进行交互,这就需要服务器实时的向所有在线玩家进行消息广播,这一点很损耗服务器性能的,在这方面,游戏后台要比web做更多的处理,游戏服务器是一个IO密集的服务器类型。

以上便是我当时的答案,或许我的见解尚浅,毕竟我做游戏不到一年,不过对于后台开发这块,我还是有一点话语权的,从实习游戏开发开始,我便经历了一个转换的过程,几乎又是一个从零开始的学习过程,从mina框架到protobuffer,这些东西,我相信web开发很少接触(mina作为网络通信框架,web中几乎只有http通信,protobuffer作为通信协议,web最多用json,其实二者形式上差别不大,但数据大小千差万别)。而游戏的逻辑,也是比web复杂得多,不得不说,web后台成熟的第三方框架是做的真的很好。

经历了上家公司的洗礼,我想我对游戏后台开发有了足够的了解,于是我找到了我现在这家公司,这家公司目前只有我一个服务器后台,做两款游戏,一款是塔防类,准备由单机改成弱联网,服务器存档,并做登录支付验证,另一款,是比较庞大的slg手游,是准备带领公司走上巅峰的项目,说一款slg带领一个公司走上巅峰一点儿不为过,我上家公司就是这样的,凭借一款《xxxx》(哈哈,名字不透露),走上人生巅峰。我之所以接受这份工作,是因为我接受挑战,从底层写起,从架构写起,这是作为一年工作经验的我想都不敢想的,不过这是一个挑战自我,证明自我的机会,我愿意接受这个挑战,人生总会有很多爬坑的时候,但爬过了坑,就真的是人生巅峰了。我接受这个工作的另一个原因,就是公司发展确实不错,以前做的单机,都是很火的(虽然我认为我自己一个人也能做,我也是学过cocos的),而现在公司也准确的把握了游戏行业的风口——slg,coc和cok的成功案例就能证明一切,mmorpg也不一定能做起来了,moba倒是有可能,但你要跟lol做不到80%的相似,我估计没人愿意在手机玩儿moba,slg或许是性价比最高的了。这么有挑战的工作,还要从架构写起,这样的挑战,我喜欢!

说说互联网业的书吧,我认为这个行业的书,分为两种,理论型的和技术型的,所谓理论型,就是长篇大论互联网发展,行业模式等,而技术型,就是类似技术的工具书,是从技能入手的书,这两种书,我家里都有,但我发现买了之后,我很少有时间看,下班没多少时间,北京上班,大多数时间都浪费在地铁上了,上班时间,看看理论型的吧,觉得啰嗦,浪费时间(后来我发现,做这行,除了会技术,你还是需要去看看牛人眼中的互联网的,你需要透过前辈的眼光看世界,不要做IT民工,要做互联网从业者),看看技术型的吧,让别人看见了感觉你太low,所以我大多数时间还是能在网上down到pdf就在电脑看,down不到百度谷歌我要研究的技术,毕竟从事这行,还是用电脑学技术好点,主要是电脑看久了眼睛会疲惫,偶尔看看纸质的书也不错的。而以前面试的时候,面试官经常问,除了大学课本,你还看什么书啊?(如果是你们,恰巧又没看什么书,你们怎么说?),我一般会说,我会自学其他技术,如cocos2dx,然后买一些技术指南之类的书看。我觉得这已经算最大夸张化了,因为大学我真的很少看书,我记忆中就看过一本C++技术类的,一本C#的,一本Android,还有其他几本是什么都不大记得了,大学毕竟十几层的图书馆,除了英语四六级的时候进去复习,其他时间感觉都浪费了这十几层的图书馆。

说说成长过程中遇到的问题吧,如果遇到我解决不了的,以前是先自己百度谷歌,看看有没有办法解决,不行就问老大,而现在,先百度谷歌,看有没有办法解决,没办法在百度谷歌,实在不行还要看框架源码如何实现,上国外论坛看外国友人如何解决,问题总能解决的,总会有办法的。当我开始学习写架构的时候,我会开始关心游戏的网络层使用什么框架,mina还是netty,数据怎么存储mysql还是mongo,是否需要缓存redis存什么,memcached存什么,缓存什么数据,数据传输用什么协议,json还是protobuffer,怎么写效率高,最高支持多少并发等等,我想这些都是我现在需要考虑的问题,当然这些都需要根据游戏具体的需求来决定的,最终服务器能否高效稳定的运行,都是取决于我的架构是否高效稳定,所以这个过程我要不断学习,不断吸取别人的经验。刚到新公司的时候,我才体会到,自己写代码其实也是一种挑战,整个后端我自己一个人实现,代码是否规范,数据如何存储,都是我说了算,我想我的代码不仅要高效,还要让别人看得懂,后来的人能接着我的代码继续写下去。

最后说说Java的题外话,语言之争,从未停过,为什么有人拥护Java,有人拥护PHP,有人喜欢C#,有人喜欢C++,各个语言各有各的优势,业余时间,我也了解了不少其他语言,go,node.js我都有了解,我觉得go的语言层面支持协程并发以及node.js的异步,都是很适合游戏服务器的,我特别看好node.js,异步io真的是对游戏服务器很好的特性,并且加入对原声js支持的mongo模块也是很方便的(上面我有说到,我相信nosql是很适合存储游戏数据的)。说到游戏行业,我认为h5游戏的发展也是越来越快了,上次白鹭的h5开发者生态大会我去了,白鹭的一整套工作流程,以及web vr,真的很令人兴奋(第一轮抽奖我还抽了一个暴风魔镜,哈哈!),另外,大会的模特挺漂亮,哈哈!2015年,互联网行业也略呈下降趋势了,不少创业公司面临倒闭,泡沫经济破灭,因为很多老板抓不住当前经济形势,以为不管是啥,有个app就是创业了,其实全然不知一款app后面有多少运营模式、盈利模式,就像一句讽刺的话,“我有个绝壁好的idea,可以颠覆bat,什么都不缺,就缺个程序员了,等等,千万别告诉马云!”,哈哈,听到这句话,当时我就笑了,估计好多倒闭的创业公司老板都这么想的吧,他们并不能抓住用户真正的需求,只有抓住用户真正的需求,才会抓住用户的心,真正活下来的,才是用户真正需要的,然而,相对来说,游戏行业更是复杂多变,或许今天玩家喜欢这种游戏,明天玩家就喜欢另一种游戏了,就像我们永远也想不到,flappy bird、围住神经病猫这类的游戏竟然能活起来,愚公移山竟然也能让h5游戏变为付费的可能。就像一句话,“只要站在风口上,猪也能飞起来!”,只要抓住了玩家此时此刻真正想要的,产品就一定能做起来。

Android系统广播(Broadcast)注册,发送,接收流程解析

以下广播简称Broadcast

   是Android四大组件之一,在四大组件的另外两个组件 和 拥有发送和接收广播的能力。Android 是在 进程间通信机制的基础上实现的,内部基于消息发布和订阅的事件驱动模型,广播发送者负责发送消息,广播接收者需要先订阅消息,然后才能收到消息。 进程间通信与 的区别在于:

   有三种类型

   存在一个注册中心,也可以说是一个调度中心,即 。广播接收者将自己注册到 中,并指定要接收的广播类型;广播发送者发送广播时,发送的广播首先会发送到 , 根据广播的类型找到对应的 ,找到后边将广播发送给其处理。

   这里以普通广播为例子, 接收者有两种注册方式,一种是 ,一种是 :

(广播的发送分为 两种,这里针对有序的广播) 中的android:priority=""和 中的IntentFilter.setPriority(int)可以用来设置广播接收者的优先级,默认都是0 , 范围是[-1000, 1000],值越大优先级越高,优先级越高越早收到。

   在相同优先级接收同个类型广播时, 的广播接收器比 的广播接收者更快的接收到对应的广播,这个之后会进行分析。

   注:以下源码基于rk3399_industry Android7.1.2

   的流程可分为 , 和 三个部分,这里依次分析下

   在Android系统的 机制中,前面提到, 作为一个注册和调度中心负责注册和转发 。所以 的注册过程就是把它注册到 的过程。

   这里我们分析 广播的过程, 和 有一个共同的父类 ,所以它们对应的注册过程其实是调用 ,接下来我们按照流程逐步分析调用流程的源码。

frameworks/base/core/java/android/content/ContextWrapper.java

   在之前的 Android应用程序启动入口ActivityThread.main流程分析 分析过,在我们启动 Activity 时会创建一个 对象,然后通过 传给我们启动的 ,其内部就会将该对象赋值给 ; 的 方法也是类似的赋值流程,这里放个简易的源码应该更好理解

   可以看到最后都会将生成的 对象赋值给对应的

对象。接下来继续分析 , 即 函数。

/frameworks/base/core/java/android/app/ContextImpl.java

   这里我们首先看下如何将广播接收者 封装成一个 接口的 本地对象

/frameworks/base/core/java/android/app/LoadedApk.java

   每一个注册过广播接收者的 或 组件在font color='Crimson' LoadedApk /font类中都有个对应的 对象,该对象负责将 与 组件关联起来。这些对象,以关联的 作为关键字保存在一个 中。之后对应的 又以 的 作为关键字保存在 的成员变量 对象中。最后通过 对应的 方法获得其 接口的 本地对象。之后再回到 注册方法内,将 对象发给 进行注册。

/frameworks/base/core/java/android/app/ActivityManagerNative.java

/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

   在的 或 注册一个 时,并不是将其注册到font color='OrangeRed'AMS/font中,而是将与它关联的font color='OrangeRed'InnerReceiver/font对象注册到font color='OrangeRed'AMS/font中,当font color='OrangeRed'AMS/font接收到广播时,会根据 在内部找到对应的font color='OrangeRed'InnerReceiver/font对象,然后在通过这个对象将这个广播发送给对应的 处理。

   注册过程这边画了一个简单的流程图:

   font color='OrangeRed'Broadcast/font的发送过程可简单描述为以下几个过程:

frameworks/base/core/java/android/content/ContextWrapper.java

/frameworks/base/core/java/android/app/ContextImpl.java

/frameworks/base/core/java/android/app/ActivityManagerNative.java

/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

关于java消息广播和java电台的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。

The End

发布于:2022-12-15,除非注明,否则均为首码项目网原创文章,转载请注明出处。