WHH

MY BLOG

在物理机中,为了加快处理器与内存交互速度,在处理器中引入了高速缓存,将运算需要使用到的数据复制到缓存中,运算结束后再从缓存同步到内存中。这样在多线程处理数据时,可能会导致不同处理器中缓存数据不一致,这个时候引入了缓存一致性协议,这样能保证一个处理器修改了数据,其他处理也能看到最新的数据。

在Java虚拟机规范中定义了一种Java内存模型(Java Memory Model, JMM)来屏蔽各种硬件和操作系统的内存访问差异,让Java程序在不同平台都能达到一致的内存访问效果。(JDK1.5之后内存模型才相对完善)

在Java中,所有实例域、静态域和数组元素存储在堆内存中,堆内存在线程之间共享(代指实例域,静态域和数组元素)。局部变量(Local variables),方法定义参数(java语言规范称之为formal method parameters)和异常处理器参数(exception handler parameters)不会在线程之间共享,它们不会有内存可见性问题,也不受内存模型的影响。

Java内存模型规定了共享变量存储在主内存中,每条线程都有自己的工作内存(线程本地内存),工作内存中存储被该线程使用到的变量的主内存的副本(不是整个对象的内存复制,对象的引用、线程访问的字段)。如图:

阅读全文 »

volatile定义与实现原理

Java编程语言允许线程访问共享变量,为了确保共享变量能被准确和一致的更新,线程应该确保通过排他锁单独获得这个变量。Java语言提供了volatile,在某些情况下比锁更加方便。如果一个字段被声明成volatile,Java线程内存模型确保所有线程看到这个变量的值是一致的。(Java语言规范第三版volatile定义)

volatile主要作用为:

  1. 禁止指令重排序优化
  2. 保证内存一致性

因为在写操作volatile修饰的变量时,会多出一行lock汇编代码。
在cpu操作时,会把部分数据缓存到CPU缓存里(L1、L2等)并未实时写回内存,如果对声明了volatile的变量进行写操作,会将当前变量所在的缓存行数据写回到系统内存,在多处理器下,为了保证其他处理核心缓存一致,会实现缓存一致协议,保证其他处理器检查当前缓存是否过期,后续操作时,会重新从系统内存中读取最新数据到缓存。简单来说,修改了volatile修饰的变量时,把CPU缓存中修改后的值及时写入内存,同时其他处理器设置自己缓存过期,使用时重新从系统内存中读取。

阅读全文 »

环境

  • jdk1.8

并发编程基本概念

为了利用多核处理器,采用多线程编程能节省大量运行时间,带来的缺点是会导致程序复杂度的提升。

并行、并发
并行:两个任务同时运行,如启动多个线程,每个线程运行各自的任务,在多核处理器中,不同的任务同时运行,可视为并行。(单核系统不存在并行)
并发:多个线程同时访问一个任务。

同步、异步
同步:调用一个方法,必须等待该方法返回后,才能继续下一步。
异步:调用方法后,必须等待方法的返回,继续执行下一步。在Java中被调用的方法,一般会在另一个线程里面继续执行。

临界区
用于多线程的互斥访问。如果有多个线程试图同时访问临界区,那么在有一个线程进入临界区后,其他试图访问的线程将被挂起,直到进入临界区的线程离开。临界区在被释放后,其他线程可以继续抢占,并以此达到对临界区的互斥访问。

阻塞、非阻塞
阻塞:在一个线程占用了临界区的资源,其他线程想要进入临界区需等进入临界区的线程释放资源,这时是其他等待的线程被阻塞挂起。
非阻塞:没有线程妨碍其他线程执行。

阅读全文 »

项目背景

因为企业内部无外网,需要一个内部通讯工具,考虑买RTX或者内部开发一个,前期做相关技术调研,评估自己实现难度。定的技术方案PC端使用QT做界面,服务端使用Tigase,使用XMPP通讯。主要功能有:单聊、群聊、组织结构、文件、图片发送。

QT使用

QT使用qml做页面,其他相关逻辑采用c++,与服务端通讯采用QXMPP框架。
因为没用QT开发过,在github上找到WinT-Messenger开源项目,了解相关代码编写。

在使用QT过程中,主要难点在于:

  1. 布局:需要了解熟悉QT的各种布局
  2. c++与QML直接通讯,c++与服务端通讯
  3. QT相关常用组件
    阅读全文 »

Tigase插件

Tigase插件被SessionManager组件和C2S所加载。

新建一个maven项目,添加tigase-server依赖

1
2
3
4
5
<dependency>
<groupId>tigase</groupId>
<artifactId>tigase-server</artifactId>
<version>7.1.2</version>
</dependency>

复制之前教程idea启动Tigase中的etc目录到该maven项目根目录下。
项目中创建java文件DemoPlugin

1
2
3
4
5
6
7
8
9
10
11
12
@Id(DEMO)
@Handles(
@Handle(path = "message", xmlns = "jabber:client")
)
public class DemoPlugin extends AnnotatedXMPPProcessor implements XMPPProcessorIfc {
protected static final String DEMO = "DEMO";

@Override
public void process(Packet packet, XMPPResourceConnection session, NonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings) throws XMPPException {
System.out.println("~~~~~~~" + packet.toString());
}
}

AnnotatedXMPPProcessor表示可以通过注解配置插件。插件处理消息有:

  • XMPPPreprocessorIfc - is the interface for packets pre-processing plugins.
  • XMPPProcessorIfc - is the interface for packets processing plugins.
  • XMPPPostprocessorIfc - is the interface for packets post-processing plugins.
  • XMPPPacketFilterIfc - is the interface for processing results filtering.

process代码写习惯业务逻辑。注解表示该插件的唯一ID,以及需要处理指定的消息。
在配置文件init-mysql.properties中,添加–sm-plugins=+DEMO,如果已经有该配置,在后面添加+DEMO即可。这里+表示添加插件,默认为+,修改为-表示去除插件,可以在SessionManagerConfig类中查看默认加载的插件。

配置tigase.server.XMPPServer启动项目即可。

阅读全文 »

访问者模式

提供一个作用于某对象结构中的各元素的操作表示,它使我们可以在不改变各元素的类的前提下定义作用于这些元素的新操作。访问者模式是一种对象行为型模式。

访问者模式是一种较为复杂的行为型设计模式,它包含访问者和被访问元素两个主要组成部分,这些被访问的元素通常具有不同的类型,且不同的访问者可以对它们进行不同的访问操作。

访问者模式的目的是封装一些施加于某种数据结构元素之上的操作。一旦这些操作需要修改的话,接受这个操作的数据结构则可以保持不变。

UML类图如下:

阅读全文 »

模板方法

定义一个操作中算法的框架,而将一些步骤延迟到子类中。模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。模板方法模式是一种基于继承的代码复用技术,它是一种类行为型模式。

模板方法模式是结构最简单的行为型设计模式,在其结构中只存在父类与子类之间的继承关系。通过使用模板方法模式,可以将一些复杂流程的实现步骤封装在一系列基本方法中,在抽象父类中提供一个称之为模板方法的方法来定义这些基本方法的执行次序,而通过其子类来覆盖某些步骤,从而使得相同的算法框架可以有不同的执行结果。模板方法模式提供了一个模板方法来定义算法框架,而某些具体步骤的实现可以在其子类中完成。

阅读全文 »

策略模式

定义一系列算法类,将每一个算法封装起来,并让它们可以相互替换,策略模式让算法独立于使用它的客户而变化,也称为政策模式(Policy)。策略模式是一种对象行为型模式。

在策略模式中,我们可以定义一些独立的类来封装不同的算法,每一个类封装一种具体的算法,在这里,每一个封装算法的类我们都可以称之为一种策略(Strategy),为了保证这些策略在使用时具有一致性,一般会提供一个抽象的策略类来做规则的定义,而每种算法则对应于一个具体策略类。

UML类图如下:

阅读全文 »

状态设计模式

允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。其别名为状态对象(Objects for States),状态模式是一种对象行为型模式。

状态模式用于解决系统中复杂对象的状态转换以及不同状态下行为的封装问题。当系统中某个对象存在多个状态,这些状态之间可以进行转换,而且对象在不同状态下行为不相同时可以使用状态模式。状态模式将一个对象的状态从该对象中分离出来,封装到专门的状态类中,使得对象状态可以灵活变化,对于客户端而言,无须关心对象状态的转换以及对象所处的当前状态,无论对于何种状态的对象,客户端都可以一致处理。

UML类图如下:

阅读全文 »

因为企业内部需要使用IM,现通Tigase+Spark搭建初始项目。

下载源码

访问Tigase官网,为了二次开发,下载Tigase源码。
下载地址:https://tigase.tech/projects/tigase-server/repository

1
2
3
4
5
#下载源码
git clone https://git.tigase.tech/tigase-server.git
cd tigase-server
#切换到最新tag
git checkout tigase-server-7.1.2
阅读全文 »
0%