一、元注解:描述注解
●使用位置 @Target() 重要
值的类型为枚举类型
枚举类型名,属性名
ElementType.TYPE:类接口 枚举
ElementType.CONSTRUCTOR:构造方法
ElementType.METHOD:普通方法
ElementType.FIELD:属性
ElementType.LOCAL_VARIABLE:局部变量
ElementType.PARAMETER:方法的参数
ElementType.ANNOTATION_TYPE:注解
●保留到什么时候 @Retention() 重要
值的类型为枚举类型
枚举类型名.属性名
RetentionPolicy.SOURCE:保留到源文件中,进行了编译会被舍弃
RetentionPolicy.CLASS:保留到字节码文件中,字节码文件被jvm加载,舍弃该注解RetentionPolicy.RUNTIME:保留到运行时,程序运行过程中可以使用
●是否生成java文档时记录到文档 @Documented
●子类可以维承父类中的注解 @Inherited
二、生成jar包-指定主方法
•实例化 创建对象语法格式:
数据类型 变量名|对象名=new 数据类型();
•属性赋值:
对象名.属性名=值:
•获取属性值:
数据类型 变量名=对象名.属性名;
●手写IOC
• IOC (Inversion of Control即控制反转):不需要手动创建,将手动创建对象交给容器创建
①在xml中配置类的相关信息
②解析xml中类的信息,创建对象,完成属性赋值
③将创建好的对象存储在容器中,需要使用对象时,在容器中获取对象即可
●编写dtd
需要被打包的内容需要放置在src中,dtd为xml的约束,需要将dtd文件存放在src目录中
●编写dtd内容
三、Swing
AWT(Abstract Windowing Toolkit)抽象窗口工具包,是JDK提供的一套桌面程序开发工具包。调用里面的API可以实现桌面程序。
Swing:为解决AWT存在的问题而新开发的图形界面包。
四、线程
●进程
系统中正在运行的一个应用程序。当在系统中启动一个程序后,系统会为该程序分配至少一个进程。
当某个软件无响应时,可以通过在任务管理器中强制关闭软件的进程。
●线程(Thread)
线程是操作系统运行调度的最小单位。一个进程中至少会有一个线程。
一个线程就是程序代码的顺序执行的过程,代码逐行执行,执行时下面代码必须等待上面代码执行完成。在Java中主方法对应的就是程序的主线程。当启动应用程序运行主方法就是运行在主线程中。
一个类中只能存在一个主方法,所以只能有一个主线程。
执行时就是从上往下依次执行:每行代码执行时,下边的代码会等待上边代码执行结束,才会按照顺序继续往下执行。
●线程休眠
在一个线程中代码都是顺序执行的,上面代码执行完成才会执行下面代码。这也叫做线程的阻塞性。
使用输出语句可以感受线程的顺序执行,但是不能感觉到阻塞性。为了能够更清楚明白线程的阻塞性,可以通过Thread.sleep0;方法感受。
•Thread中sleep方法中
①实现功能:哪个线程调用sleep(方法,就让哪个线程休眠多少毫秒。给人的感觉是执行Thread.sleep(n);时花费了n毫秒,实际为该线程休眠了n毫秒(注:1000毫秒=1秒)
②因为方法是static的,所以可以直接使用类名调用。
③参数是休眠多少毫秒。
④native关键字表示方法的实现调用了另一种编程语言的代码。具体说明底层使用C语言实现的。
●多线程
操作系统内部支持多进程,而每个进程的内部又是支持多线程的,线程是轻量级的,新建线程会共享所在进程的系统资源目前主流的开发都是采用多线程。多线程是采用是间片轮转法来保证多个线程的并发执行,所谓并发就是指宏观并行微观串行的机制。
多线程:一个进程中包含多个线程。
多线程的调度,执行等都是由硬件CPU负责的。
利用多线程,让程序具备了多任务处理能力。
我们可以在主线程中创建多个线程,这些线程称为子线程。
子线程不会阻塞主线程的执行,子线程中代码可以和主线程中代码同时执行。
●并发与并行
•并发:
同一时刻只能有一个线程执行,但是多个线程被快速的轮换执行,使得在宏观上具有多个线程同时执行的效果,但在微观上并不是同时执行的,只是把CPU运行时间划分成若干个时间段,再将时间段分配给各个线程执行
处理器的每一个核处理多个任务,超过了能处理的范围,同一时间间隔处理
•并行:
一个以上的CPU或者一个CPU有多核,当一个CPU执行一个线程时,另一个CPU可以执行另一个线程,两个线程互不抢占CPU资源,可以同时进行
多个处理器或者多核的处理器同时处理多个任务,同时处理
●应用程序、进程、线程的关系
一个应用程序对应一个进程。
一个进程可以包含多个线程。
所以:一个程序关闭了,在系统中的进程就没了,程序中的线程也结束了。
五、创建线程
●Thread类
java.lang.Thread类代表线程,任何线程对象都是Thread类(子类)的实例
Thread类是线程的模板,封装了复杂的线程开启等操作,封装了操作系统的差异性
●创建方式
在Java中创建线程有三种实现方式。
•继承Thread类,重写run方法。
•实现Runnable接口,重写run方法。
•实现Callable接口,结合Future。
●相关方法
•Thread() 根据无参构造方法创建线程对象
•Thread(String, name) 根据参数指定线程名字,创建线程对象
•Thread(Runnable target) 根据参数指定的引用创建线程对象.Runnable为接口类型•Thread(Runnable target, String name) 根据参数指定的引用和线程名字创建线程对象.Runnable为接口类型
●创建线程:
方式一:继承Thread类,重写run()方法
•继承Thread类,重写run()方法(run方法中编写子线程执行的任务)
•创建子类对象
•调用start()方法
•start()方法中自动调用starte()
•starte()方法的实现由c c++做的实现,开启线程,自动调用run()方法,由于run()方法被重写,执行重写之后的run()方法
方式二:实现Runnable接口,实现run()方法
•调用Thread(Runnable target)构造方法,需要传递Runnable实现类对象(Runnable实现类实现run方法,run方法中编写任务)
•将Runnable实现类对象赋值给target属性
•调用start()方法
•start()方法中自动调用starte()
•starte()方法的实现由c|c++做的实现,开启线程,自动调用Thread类中的run()方法
•Thread类中run()方法中,target属性不为nu1l,调用Runnable实现类中的run()
方式三;实现Callable接口,实现cal1()方法
•调用Thread(Runnable target)构造方法,需要传递Runnable实现类对象(FutureTask类为jdk提供的Runnable接口实现类,实现了run()方法)
•将Runnable实现类FutureTask对象赋值给target属性
•调用start()方法
•start()方法中自动调用starte()
•starte()方法的实现由c|c++做的实现,开启线程,自动调用Thread类中的run()方法.
•Thread类中run()方法中,target属性不为nu11,调用Runnable实现类FutureTask中的run()FutureTask中的run()方法为源码中的方法,不能修改
•执行FutureTask中的run()方法,run()方法中调用了cal1()方法(Callable实现类中实现的ca11()方法)
●调用start()方法后:
执行Thread类中的run()方法 调用 Runnable实现类FutureTask中的run()方法 调用 Callable实现类中的ca1l()
call()执行后将方法返回值返回到FutureTask中,使用outcome变量进行存储
使用FutureTask中的get()方法获取outcome变量值
●总结
①后两种方式可以避免java中的单继承的局限性。
②需要返回值只能使用实现Callable接口。
③不需要返回值推荐使用实现Runnable接口。
④线程池只能使用Runnable或Callable类型参数,不能使用继承Thread类。
●执行流程总结
①执行main()方法的线程为主线程,执行run0方法的线程为子线程。
②main()方法是程序的入口,对于start()方法之前的代码来说,只有主一个线程,当一个start()方法调用成功后线程由1个变成2个,新启动的线程去执行run方法的代码,主线程继续向下执行,两个线程各自独立运行互不影响。
③子线程执结束和主线程执行结束,程序结束。
④两个线程执行没有明确的先后执行次序,由操作系统调度算法来决定。
六、JMM
●内存模型可以理解为在特定的操作协议下,对特定的内存或者高速缓存进行读写访问的过程抽象描述,不同架构下的物理机拥有不一样的内存模型,Java虚拟机(jvm)是一个实现了跨平台的虚拟系统,也有内存模型,即Java内存模型(Java Memory Model, JMM)
●线程/工作内存/主内存三者的关系
①所有变量都存储在主内存中,主内存是共享内存区域,所有线程都可以访问
②每个线程都有一个独立的工作内存,用于存储线程私有的数据
③线程对变量的操作必须在工作内存中进行(线程安全问题的根本原因)
首先要将变量从主内存拷贝到线程的工作内存中,主内存是共享内存区域,所有线程都可以访问
每个线程操作自己工作内存中的变量副本,操作完成后再将变量写回主内存
不同的线程间无法访问对方的工作内存,线程间的通信(传值)必须通过主内存来完成
●JMM的三个特性
•可见性
在Java中,不同线程拥有各自的私有工作内存,当线程需要修改某个变量时,不能直接去操作主内存中的变量,而是需要将这个变量读取到该线程的工作内存中(变量副本),当该线程修改其变量副本后,其它线程并不能立刻读取到新值,需要将修改后的值刷新到主内存中,其它线程才能从主内存读取到修改后的值,
•原因:工作内存和主内存存在同步延迟
•解决方案:
•volatile:可以保证内存可见性
① 规定线程每次修改变量副本后立刻同步到主内存中
②规定线程每次使用变量前,先从主内存中拷贝最新的值到工作内存中,用于保证能看见其它线程对变量修改的最新值
•synchronize:同步锁
注意:
volilate可以保证可见性,但是假设多线程同时在做a++,在线程A修改共享变量从0到1的同时,线程B已经正在使用值为0的变量,所以这时候可见性已经无法发挥作用,线程B将其修改为1,所以最后结果是1而不是2
•有序性
在单线程程序中代码逐行执行,但是在多线程并发时,程序的执行就有可能出现乱序,
多线程执行程序时,为了提高性能,编译器和处理器常常会自动对指令做重排序,目的是进行相关的优化,指令重排序使得代码在多线程执行时可能会出现一些问题
•解决方案:
①volatile:可以保证有序性
在指令序列中插入内存屏障(一组处理器指令),防止指令重排序
②synchronize:同步锁
•原子性
原子性指一个操作是不可中断的。即使是在多个线程一起执行的时候,一个线程的操作一旦开始,就不会被其他线程干扰,只能当前线程执行完,其他线程才可以执行
•解决方案:
①synchronize:同步锁
●volatile可以解决可见性,有序性,但是不能解决原子性;
synchronize可以解决可见性,有序性,原子性
七、MySQL:关系型数据库管理系统
●数据(data)
数据是指对客观事物描述并可以鉴别的符号,这些符号是可识别的,抽象的。它不仅仅指狭义上的文本(数字,字母,字符等),数据还有多种表现形式:图形、音频、视频等。
●数据库(database)
数据库(DataBase,简称DB),就是存储数据的仓库。
其本质就是一个文件管理,就是以文件的形式将数据保存到电脑的磁盘中。
●数据库管理系统(DBMS)
数据库管理系统(Database Manage System,简称DBMS):操作,管理及维护数据库的大型软件。
MySQL就是数据库管理系统软件,安装了MySQL的电脑,也可以称为数据库服务器。
作用:用于建立,使用和维护数据库,对数据库进行统一的管理。
●数据库应用程序
数据库应用程序(Database Application System,DBAS)是在数据库管理系统基础上,使用数据库管理系统的语法,开发的直接面对最终用户的应用程序。
●数据库管理员
数据库管理员(Database Administrator,DBA)是指对数据库管理系统进行操作的人员,其主要负责数据库的运营和维护。
●数据库的分类
●关系型数据库
关系型数据库是将复杂的数据结构用较为简单的二维表来表示,由二维表及其之间的联系所组成的一个数据组。
在该类型数据库中,对数据的操作基本上都建立在一张或多张表上,采用结构化查询语言(SQL)对数据库进行操作,关系型数据库是比较主流的数据库技术。
•优点:
①易于维护:使用二维表的表结构,格式一致;
②使用方便:SQL语言通用,关系型数据库都可以使用SQL进行操作;
③复杂操作:可用于一个表以及多个表之间非常复杂的查询。
•缺点:
①读写性能比较差,尤其是海量数据的高效率读写;
②固定的表结构,灵活度稍欠;
③高并发读写需求,传统关系型数据库来说,硬盘1/O是一个很大的瓶颈。
●非关系型数据库
非关系型数据库也称之为NoSQL(Not Only SQL)数据库,是一种数据结构化存储方法的集合,可以是文档或者键值对等。
•优点:
①格式灵活:存储数据的格式可以是key,value形式,文档形式,图片形式等等.
②使用灵活,应用场景广泛,而关系型数据库则只支持基础的类型
③速度快:使用内存存储数据,而关系型数据库只能使用硬盘
④高扩展性
•缺点:
①不提供sql支持,学习和使用成本较高
②数据结构相对复杂,复杂查询方面稍欠
③只适合存储一些较为简单的数据,对于需要进行较复杂查询的数据,关系型数据库显的更为合适
④不适合持久存储海量数据