标签: java

java

设计模式之单例模式

一.什么是单例模式?单例模式是设计模式中最简单的一个设计模式,属于创建型模式,其定义是保证一个类***仅有一个实例***,并且提供一个访问它的全局访问点。单例模式一般体现在类声明中,单例的类负责创建自己的对象,同时保证只有单个对象被创建,并且提供一个访问它的全局访问点,可以直接访问,不需要实例化对象。二.为什么需要用到单例模式?由于单例模式只创建了一个实例,减少了内存的消耗,在一些频繁创建销毁实例的情景下可使用避免对资源的多重占用,比如文件写操作在一些特定的情境下必须使用单例,如一个国家只能有一个主席三.如何使用单例?我们知道一个类的对象的产生是通过它的构造函数来实现的,如果一个类对外提供了一个public的构造方法,那么外界就可以任意创建这个类的对象。所以当你想限制类的产生时,就需要把构造函数设为私有的(至少也是受保护的),并且需要提供一个对象以及访问这个对象的静态方法。1.饿汉式单例模式publicclassTest{//在类的内部实例化一个实例privatestaticTesttest=newTest();//私有的构造函数,外界不能访问privateTest(){}//对外提供的获取实例的静态方法publicstaticTestgetTest(){returntest;}}@Testpublicstaticvoidmain(String

java

基于ssm的数据库课程设计

数据库课程设计数据库课程设计说明:1.使用的技术栈:前端:layui前端UI框架后端:基于Java的Spring+SpringMVC+MyBatis框架数据库:MYSQL数据库2.功能:该学生选课管理系统分为三端:学生端,教师端和管理员端管理员端:管理员可以查看学生,教师,班级,选课列表,并对学生,教师,班级信息进行增删改查,实现了数据分页功能,管理员还可以对学生选修课程可以管理。教师端:教师可以查看选修了自己课程的学生信息,查看个人信息,所在班级信息,对自己所教课程进行编辑,添加课程,查看所教学生的课程信息。学生端:学生可以查看个人信息,所在班级信息,可以查看自己选修的课程信息,如总学分,总分等等,学生还可以对未选修的课程进行选课,并且可以退选课程。(1)E-R图(2)关系模式R1(id,学号,姓名,性别,班级序号,年龄,手机号,密码),主码:id和学号外码:班级序号R2(id,班级编号,班级名称,班级简介),主码:idR3(id,课程名称,教师编号,上课时间,选修人数,最大人数,学分),主码:id外码:教师编号R4(id,教师编号,名称,班级编号,性别,职位,工资,密码)主码:id外码:班级编号R5(id,管理员账号,密码)主码:idR6(id,学生id,课程id,教师id,分数)主码:id外码:学生id,课程id,教师id(3)实验截图1.主界面,实现学生,教师和管理员三端登录,并分别授予不同权限。2.管理员界面管理员界面分别有学生管理,班级管理,教师管理,课程管理和选课信息管理模块(1)学生管理模块:学生管理模块可以进行指定条件搜索学生信息功能,添加功能,删除功能以及编辑功能。(2)教师模块:功能与学生模块类似,就不一一截图(3)班级管理模块:(4)课程管理(5)选课信息管理模块可以对学生选课进行管理,为学生选课,退课,并且可以为学生添加成绩3.教师界面教师界面可以查看选修了自己课程的学生信息,查看自己的班级,查看自己的信息并编辑相关信息,查看自己的课程并添加,编辑和删除课程。3.学生界面:学生界面可以查看自己的信息,并且可以编辑指定个人信息,可以查看所在班级信息,也可以查看自己选修课程信息,且可以对课程进行选课,退课项目地址:GitHub

java

深入理解JVM(一)

深入理解java虚拟机笔记(一)第一章走进java第一章主要介绍了java的发展史和JDK编译。java发展史粗略看了下,了解一下即可。至于JDK编译,暂且跳过,等有时间,有需要去阅读JDK源码时在去实操。第二章java内存区域与内存溢出异常2.1概述在内存管理领域,c++开发人员即可以拥有一个对象的“所有权”,又需要肩负对每个对象从开始到结束的维护责任。而对于java开发人员来说,java虚拟机就是个boss级别的存在,拥有控制内存的权力,不需要为每个new操作去delete/free。但是一但遇到问题,不了解jvm,debug就会很艰难。2.2内存区域2.2.1程序计数器概念:程序计数器是当前线程所执行的字节码的行号指示器特性:分支,循环,跳转,异常处理,线程恢复等基础功能都需要依赖程序计数器,是程序控制流的指示器线程私有。各线程间的计数器互不影响,独立存储多线程运行时通过计数器恢复到正确的执行位置异常:在执行Java方法时,计数器记录的是正在执行的是虚拟机字节码指令的地址;如果执行的是一个本地(Native)方法,计数器则为空(Undefined)。这个内存区域是唯一一个没有规定任何OutOfMemoryEttor情况的区域。2.2.2Java虚拟机栈概念和存储:虚拟机描述的是Java方法执行的线程内存模型:每个方法被执行的时候,Java虚拟机都会创建一个栈帧,用于存储局部变量表,操作数栈,动态连接,方法出口等信息,每个方法被调用直至执行完毕,对应着一个栈帧在虚拟机栈中从入栈到出栈的过程,即先进后出,调用递归的原理基于此。特性:线程私有,生命周期与线程相同对于Java虚拟机栈,主要关心的就是其局部变量表的存储,在我们定义一个变量的时候,经常会被问到,这个变量到底被存储在哪里。而局部变量表存放了各种Java虚拟机基本数据类型(boolean,byte,char,short,int,float,long,double),对象引用(reference类型,一个指向对象的指针或者是一个句柄,不是对象本身)和returnAddress类型(指向了一条字节码指令的地址)。局部变量表在编译期就已经完全确定好大小了,在方法运行期间不会改变局部变量表的大小。同时,对于64位长度的long和double类型的数据会占用两个变量槽(Slot),其余数据类型只占用一个。异常:在Java虚拟机规范中,对这个内存规定了两类异常状况:StackOverflowError和ouOutOfMemoryError异常。2.2.3本地方法栈本地方法栈和Java虚拟机栈类似,唯一区别是本地方法栈是用来执行Native方法的。而有些虚拟机(Hot-Spot虚拟机)将Java虚拟机栈和本地方法栈合二为一。2.2.4Java堆概念:Java堆是虚拟机所管理的内存中最大的一块,被所有线程共享,此内存的唯一目的就是存放对象实例。Java堆还是垃圾收集器管理的内存区域。Java虚拟机规范中描述:所有的对象实例以及数组都应当在堆上分配。特性:从分配内存的角度看,所有线程共享的Java堆中可以划分出多个线程私有的分配缓冲区。Java堆可以处于物理上不连续的内存空间,但在逻辑上它应该被视为连续的。Java堆既可以被实现成固定大小,也可以进行扩展。ps:将Java堆进行细分是为了更好地回收内存,更快地分配内存。异常:在Java虚拟机规范中,对这个内存规定了ouOutOfMemoryError异常。2.2.5方法区概念:方法区是各个线程共享的内存区域,用于存储已被虚拟机加载的类型信息,常量,静态变量,即时编译器编译后的代码缓存等数据。在JDK7的时候,把原本放在永久代(不完全等价方法区)的字符串常量池,静态变量等移出;在JDK8的时候,将永久代还剩余的内容(主要是类型信息)全部移动到元空间。特性:方法区不需要连续的内存和可以选择固定大小或可扩展,还可以选择不实现垃圾收集方法区内存回收目标主要是针对常量池的回收和对类型的卸载异常:如果方法区无法满足新的内存分配需求时,将抛出OutOfMemoryError异常2.2.7直接内存概念:直接内存不是虚拟机运行时数据区的一部分,也不是《Java虚拟机规范》中定义的内存区域。特性:在JDK1.4中引入了NIO类,可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆里面的DirectByteBuffer对象作为这块内存的引用进行操作,能够显著提高性能,避免了在Java堆和Native堆中来回复制异常:动态扩展时可能会出现OutOfMemoryError异常2.3HotSpot虚拟机对象探秘2.3.1对象的创建虚拟机遇到一条new指令时,首先检查这个指令的参数是否能在常量池里定位到一个类的符号引用。并检查这个类是否已经加载,解析和初始化过,如果没有,先执行类的加载过程。类加载检测通过后,jvm为新生对象分配内存,类加载完成后,对象的内存大小就定下来了。为对象分配空间等同与把一块确定的内存从java堆中分出来。假设堆内存是规整的,有用的空闲的内存中间放一个指针当分界点,如果指针挪动,则可为对象分配空间,这种方式叫指针碰撞。假设堆内存是不规整的,jvm需要维护一个空闲列表来记录哪块内存是可用的,这种方式叫空闲列表。线程安全的解决方法:1.对分配内存空间的动作进行同步处理。2.每个线程在Java堆中预先分配一块小内存,称为本地线程分配缓冲(TLAB)。当TLAB用完后,才需要同步锁。配置方法:-XX:+/-UseTLAB。内存分配完之后,JVM将分配的内存空间初始化为0(但不包括对象头),如果使用TLAB,这一步可提前到TLAB分配时进行,这一步保证字段有初始值。接下来,JVM对对象进行必要的设置,如这个对象是哪个类的实例,hashcode等,这些都是放在对象头中。执行new之后会继续执行<init>方法,按照代码进行初始化。2.3.2对象的内存布局对象分为三块,头(header),实例数据(instancedata),对齐补充(padding)header包括两部分信息。一部分存储对象运行时数据如hashcode,GC分代年龄,锁的标志,线程持有的锁,偏向线程ID,偏向时间戳等。这部分是MarkWord,MarkWord的数据结构是不固定的。另外一部分是类型指针,如果是数组,还要记录数组的长度。实例数据存储顺序受分配策略参数和字段定义的顺序的影响,并且相同宽度的字段会被排到一起。父类的变量会被安排到子类之前。如果CompactFields设为true。则子类的较窄的变量会插入到父类变量的空隙中。对齐补充是保证对象初始地址必须是8字节的整数倍。2.3.3对象的访问定位通过栈上的reference来操作堆上的对象。句柄访问。Java堆中会分出一块内存作为句柄池,在reference中存储对象的句柄地址。对象被移动的时候不用改reference。直接指针访问。reference直接存储对象地址。节省了一次指针定位的时间开销。2.4OOM异常2.4.1Java堆溢出不断创建对象,超过容量限制。将堆的最小值-Xms与最大值-Xmx参数设置为一样可避免自动扩展。用参数-XX:+HeapDumpOnOutOf-MemoryError。可以让jvm在出现内存溢出的时候Dump出当前的内存堆转储快照以便分析。错误OutOfMemoryError:Javaheapspace如果是内存泄漏,通过工具集检查泄露对象到GCRoots的引用链,检查为什么无法回收。如果内存中的对象确实都还活着。查看某些对象是不是生命周期过长,持有时间过长等。2.4.2虚拟机栈和本地方法栈溢出HotSpot虚拟机不区分虚拟机栈和本地方法栈。栈容量由-Xss参数决定。栈的深度过大,将抛出StackOverflowError异常。内存不足,抛出OutMemoryError异常。单线程下,这两种情况一般抛出的都是StackOverflowError异常。操作系统分配给每个进程的内存是有限的,虚拟机栈+本地方法栈=2GB-Xmx-MaxPermSize。2.4.3方法区和运行时常量池溢出String:intern()是一个本地方法,如果字符串常量池中已经存在了,则返回池中这个对象的引用;否则,将此值放在常量池中,并返回这个String对象的引用。在JDK7的intern方法不会复制实例。方法区存放的主要是class的相关信息,如类名,字段描述,访问修饰符,常量池等等。2.4.4本机内存直接溢出DirectMemory的容量大小通过-XX:MaxDirectMemorySize参数指定,默认与-Xmx一致。用DirectByteBuffer类分配内存抛出内存溢出异常的时候并没有真正向操作系统申请分配内存,而是通过计算得知无法分配内存。真正申请分配内存的方法是Unsafe::allocateMemory()。由DirectMemory导致的内存溢出,明显特征就是在HeapDump文件中不会有明显的异常情况。

java

暑假实训一:基于Alpha-Beta剪枝极大极小博弈算法的五子棋AI实现

1、实训目标通过设计和开发移动应用产品,学习和掌握以下方法和技术项目分析及解决思路产品原型设计产品界面设计Java高级编程极小极大值算法学习及应用Alpha-Beta剪枝算法学习及应用2、实训模块1.棋盘绘制绘制五子棋棋盘2.五子棋的人人对弈实现实现双方手动下五子棋,定义下棋规则,判断下棋输赢3.五子棋的人机对弈实现初步实现人机对弈,采用估值函数和搜索树4.基于极大值极小值算法的优化初步进行对弈优化5.基于Alpha-Beta剪枝算法优化对算法进一步优化

open

该博客目前已迁移到另外一个站点链接——http://blog.datealive.top/。需要更换友链请前往此站进行交换,望谅解