Rich Client:胖客户端(集成了系统的大部分业务逻辑)
C/s
b/s(瘦客户端)三层架构,多层架构
客户端 中间的业务逻辑层(可以细分为多层) 数据库层
chapter 01:补充:
一:语言=数据结构+算法+编译原理+内存原理+thinking(编程思想);
二:特性:
(1)跟C/C++的比较
简单:类和类之间只有单继承,免去了多继承引发的设计冲突, (接口和接口可以多继承)
没有指针 (java 有引用)
指针:内存地址(变量的,常量的,全局变量,代码区的等等)
内存管理:
手动的内存管理方式,要求手动开辟和手动回收成对操作
java :自动的内存回收
垃圾回收:
概念:(不限定语言):对"无用内存"的回收。
无用内存:A没有引用的内存(java:没有引用的对象)
被应用程序合法占用,
B操作系统无法回收,
C但是在应用程序中通过任何路径都没有办法访问到的内存空间,
对象变量,对象的引用:专门用于存放对象在堆区的内存地址,但程序员不能直接操作。
(2)垃圾回收机制(线程)进行内存管理:
线程:独立于应用程序可以独立运行的小的任务(完整,不可分);
(3)如何进行垃圾回收
算法:
标记清扫法: 垃圾回收线程对应用程序所占有的内存空间做周期性的扫描,如果一个内存节点通过
任何路径都无法达到应用程序的参考节点,垃圾收集线程将对该节点做标记,等启动垃
圾回收任务的时候一次性的对所有作标记的节点进行回收。
优点:算法简单
缺点:没有整理
内存搬移法:from区和to区之间有用内存的“拷贝整理”的过程
优点:可以实现内存空间的整理.
缺点:可能会进行徒劳拷贝(通常在整理多次的情况下)
(4)什么时候进行垃圾回收:
内存紧张,系统闲置(垃圾收集线程的优先级很低)。
(5)垃圾回收机制的缺陷:程序员无法知道垃圾收集器启动或终止的时间,对其无法控制。
(6)System.gc()仅仅起到通知的作用,是否启动垃圾回收机制,参考(4)
c/c++:
源代码-运行:编译和连接的过程
java:
源代码-运行:编译和解释的过程
数据结构:
1.队列:first in first out
(1)需要数量不定的内存空间(动态开辟) testArray
(2)所有的添加都是在队尾添加;
第一次添加(size=0): value+1
第n次添加(size!=0):value+1
第n次添加(size=0): value+1
所有的删除都在队首删除
array[i]=array[i+1];
i+1<=size-1 ===>i<size-1;
(3)add() remove() size() print()
描述类时有:1.以属性为主:先确定属性,提供get/set方法
2.以功能为主:根据实际的业务需要来确定功能所对应的方法,再去设计属性
chapter 05
面向对象的特性:
(1).封装
基于属性:private/强制用户遵守一定的规则对属性进行操作
基于方法:private/隐藏具体的实现细节
(2).继承:extend “扩展”
通过已有的类去扩展新的类/减少代码的“冗余”
(3).多态:
“同一类域”的“不同对象”在调用“相同的方法”说的“表现不同”(即方法的实现方式不同)
2.参数的传递:
c/c++
(1).按值传递
(2).按地址传递
(3)按引用传递
引用: 对象和对象的别名
java:
(1).按值传递:值拷贝的过程,不会的传入的参数产生一次影响
(2)按引用传递:类似于c/C++按地址传递.
本质上按值传递的一种,地址的值的拷贝过程,有可能对参数所指向的内存空间有影响
指针变量:专门用于存放指针(内存地址)的内存空间.
引用:专门用于对象的地址.类似于c/c++这中的指针变量.
String和StringBuffer:在大量的字符串的连接的时候,String有可能会产生大量的垃圾,效率低下.StringBuffer适合用于大量的字符串的操作.
3.this 用于调用当前对象的引用
用法一:区分同名局部变量和实例变量.
用法二:用于调用本类的构造器.This(参数列表)
4.封装
(1)使具体的实现细节不可见
(2)"统一"(操作的方式)对用户的接口
(3)提高效率
5.重载
(1)函数名必须相同
(2)参数列表必须不同
a.参数类型不同
b.参数个数不同
c.参数顺序不同
(3)返回值类型是否相同不造成影响
6.对象创建和初始化的过程
(1)在堆区开辟对象本身所占用的内存空间
(2)在栈区里开辟对象的引用所占用的内存空间
(3)将堆区中的对象的地址返回给栈区中的对象的引用
(4)系统采用默认的方式进行初始化
(5)显示的初始化
(6)调用构造器对对象进行初始化
7.继承:extends
构造器
(1)super(参数列表);调用父类的构造器
a.必须在自类构造器的第一行使用
b.必须保证所调用的构造器存在
c.如果不在子类的构造器中调用,系统将会自动调用父类默认的构造器,如果父类的默认构造器不存在,将会出现编译错误
无论什么系统都少不了基本的“增删改查”的功能。
作业
1.一个公司需要管理员工:添加员工,删除员工,修改员工
2.企业希望给员工加薪,setSalary>800
a类员工:年薪制,根据等级加薪
level1:年薪+2000
level2:年薪+1000
level3:年薪+500
b类员工
月薪值:根据月收入加薪
800-1000: 500
1000-1500:300
>1500: 200
3.管理员要求调用addSalary(),方法后可以实现所有种类的员工的加薪
//以员工的属性为主体
//id唯一确定员工
分析所需要构造的类:
class Employee{
id;
name;
}
class EmployeeA extends Employee{
int salaryLevel;
public void addSalary(){
}
}
class EmployeeB extends Employee{
double salary;
public void addSalary(){
}
}
//以对员工的操作为主体 由管理员进行操作(相当于遥控器)
class EmployeeService{
private EmployeeData data=new EmployeeData();
public void addEmployee(int id,String name,.....){
data.add(new Employee);
}
public void removeEmployee(int id){
}
public void updateEmployee(int id,String name,.....){
}
}
用于处理员工的队列
class EmployeeData{
private Employee[] array;
private int size;
private int maxsize;
public void TestArray(){
}
public void add(Employee e){
}
public void remove(Employee e){
}
public void update(Employee e){
}
public void print(){
}
}
person
对象:现实世界的实体.
判别两个对象是否属于同一对象的标准
chapter 06 内部类
1.static:
(new Level1()).play();new Level1()为匿名对象:
匿名对象:在创建对象的时候不去创建对象的引用,该对象称为匿名对象,使用匿名对象的目的:通常只需要度某个方法调用一次,不需要做其他的操作,提高效率,简化代码.
静态变量:类似于全局变量,被所有的实例所共享.在类被加载的时候在静态存储区创建,和某个类的创建对象的个数没有关系,及始终只有一个内存空间.
class Person {
int count;
static {
//应用程序的准备工作
}
{
//可在代码区初始化变量 /但不建议这样作
}
public static void method{
}
void method1{
}
}
2.final
值能被重写的"内存空间"--变量
值不能重写的内存空间--常量
final int a=100;
final class{
}
class Test{
final public void method(){
}
}
abstract class A{
public void method();
}
使用abstract修饰的目的在于:禁止使用未被实现完整的类去创建对象.
建议:只要不希望某一个类被实例化,就可以使用abstract进行修饰.
4.接口interface
(1)所以的方法都是以声明的形式存在
(2)用于定义类必须满足的最基本的功能要求
(3)通常用于实现多态
4.equals(object 0)
class Object{
public boolean equals(object 0){}
}
public boolean equals(object 0){
//(1)判断传入的引用是否为null
if(o==null)
return false
//(2)判断传入的引用是否和当前对象所在同一地址
if(o==this)
return true;
//(3)判断传入的对象和当前对象是否精确的属于同一类
if(this.getClass()!=o.getClass())
return false;
//(4)定义自己的比较规则
Employee e=(Employee)o;
return id==e.getId();
}
}
反射:自描述,自定义
jvm(一个) application:
Person类的加载
Class类型-----实例化>Person类 实例化---new
7. 内部类
(1)成员内部类:分担外围类的功能,且在分担功能的同时依赖于外围类的资源,因为定义的方式类似于类的成员的定义方式,我们称之为成员内部类.
(2)静态内部类:分担外围类的功能,且在实现功能的时候不依赖于任何外围类的资源.(类似于C++的嵌套类)
(3)局部内部类:定义在方法内部,"通常"是方法功能的一部分;可以在完成功能的同时依赖外围类的资源.(建议方法内部的"常量"
(4)匿名内部类:类似于局部内部类的功能,在完成功能的同时可以访问外围类的资源(访问方法内部的常量)
(1)class 汽车制造厂{
public void 配件(){
}
public void 发动机(){
}
//完成组装的功能(需要依赖外围类的资源)
public class 组装分厂{
}
}
(2)class 汽车制造厂{
public void 配件(){
}
public void 发动机(){
}
//完成组装的功能(需要依赖外围类的资源)
static class 组装厂{
}
}
(3)class 汽车制造厂{
private int i;
public void 配件(){
final int a=100;
class 组装厂{
i;
a;
}
}
public void 发动机(){
}
//完成组装的功能(需要依赖外围类的资源)
}
(4) interface 组装{
}
class 汽车制造厂{
public void 配件(){
new 组装(){
public void method(){
}
};
}
public void 发动机(){
}
}
model1: 工厂模式:
在一个类中,提供一个方法,总能够产生某类对象的实例,使用户不需要自己通过new 来创建对象.
当创建对象的过程比较复杂(如:创建内部类的对象,需要向构造器中传入大量的参数)
class KFC{
public static 套餐 get套餐(double money){
return new 厨房().method();
}
class 厨房//(生产套餐){
//生产套餐
}
}
(1)成员内部类
需求:(可以存放"重复"equals--->true的对象)
实现一个可以管理任何类型的对象的数据结构,(实现添加,删除,遍历等原始功能)
通用性:
//用来定义管理可重复的对象的实现类的基本功能
=========================================================================================================
interface List
{
add/remove/index---
}
class arrayList implements List
{
}
class EmployeeData
{
private Employee [] array;
}
1.对于所有的数据结构(管理可重复对象的数据结构)的同一遍历方式:
目的相同,实现是不同的
数组,链表:
目的 (遍历)相同 ,实现是不同的
方法 无法实现
定义管理可重复的对象的实现类的统一遍历规则
interface Iterator //迭代器
{
// 判断当前位置的下一个元素是否存在
public boolean hasNext();
//上前一步,获得“当前位置的对象的引用
public Object next();
public void remove();
}
//定义管理可重复的对象类的基本功能要求
interface List
{
}
集合:
java版的数据结构。
作用:“存储”及“管理”对象,并且可以实现对一组对象的“统一操作”(遍历)
import java,util.*;
分支一:
1.collection:定义了管理对象的最基本的操作要求,如:add,remove等基本操作。
2.list:定义了管理可重复对象的实现类的规则
实现类:
arrayList:
通过数组实现list,检索速度快,但插入或删除的效率低下
不建议对象数量变化过快的情况下使用。
LinkedList:通过链表实现List。检索速度相对郊慢,但插入和删除效率相对较高。
Vector:线程安全的ArrayList
所有的方法都用synchronized修饰
class 电话停
{
synchronized public void call()
{}
}
3.Set:定义了管理不可重复的实现类的规则。
HashSet:
散列表:双向开辟内存(弹簧)
对象存放在hashSet中的定位方式:
对象的hashCode()%“当前”的散列表的长度8%10 18%10
--->8%12,18%12 地址是算出来的,所以检索速度很高(几乎最高)
特点:检索效率很高。
hashCode()不同,equals()为true是否可以放入HashSet?
算法的缺陷;先确定位置,位置重复才equals;
包装:保证放入hashset中的对象绝对不同
class MyHashSet
{
private Set set=new HashSet();
public void add(Object o)
{
if(!ifFind(o))
set.add(0);
}
public boolean isFind(Object o)
{
Iterator iter = set.iterator();
while(iter.hasNext())
{
if(iter.next().equals(o))
return true;
}
return false;
}
}
对象应该存放在散列表中的位置发生冲突的时候,“才”会调用equals()方法去比较来两个对象是否相同,如果相同,不去存放,如果不同:
散列表的长度将自动发生变化,尽量使存放的对象平均分配在散列表中。
使用hashset:建议重写以下俩个方法:
public voolean equals(Object o){}
public int hasCode(){}
class Object
{
public boolean equals(Object o){}
public String toString(){}
public int hashCode(){}
}
4.在SortedSet:在set的功能基础上进行排序。
the standant of sort is very important!!
TreeSet: 要求必须事先说明对象的排序方式
(1)排序方式一
集合所管理的对象所属的类来实现,用于定义原始的排序规则;
interface Comparable
{
public int compareTo(Object o)
{}
}
(2)排序方式二
在创建TreeSet对象的时候传入新的排序规则,用于覆盖默认的排序规则。
interface comparator
{
public int compare(Object o1,Object o2);
}
Set set= new TreeSet(new Comparator()
{
public int compare(Object o1,Object o2)
{
//覆盖的排序规则 }
});//对第一种的补充
分支二:
1.Map:通过类似于主键的方式管理对象
key(键:Object)——value(值:被管理的对象Object):一一对应的关系
map:通过一个对象(key)唯一确另一个对象(value)的管理方式
HashMap:
存放元素:put(Object key,Object value);
取出元素:Object value=get(Object key);
Set set=map.keySet();
获得map中所有key所组成set类型的对象
Hashtable:(线程安全)(t小写)!!!
2.SortedMap:在Map功能的基础之上进行排序
TreeMap:定义排序规则,定义方式同TreeSet
Map.Entry:键值对类型
Set entries = map.entrySet();
返回map中所有的键值对所组成的set集合
内部类
分担外围类的功能(整合)
“代理”
class 中介
{
public static 代理人 get代理()
{
return new 代理人();
}
class 代理人
{
。。。。。。。。。
}
}
反射:自描述,自定义(自我说明)
(1)更改私有属性的值(不通过set方法)
class Person
{
private String name;
}
(2)可以调用任何对象的任何方法
(3)可以不通过new去实现对象的创建(中间件的常用方式)
步骤:
(1)获得Class类型的对象
a、Class c=Class.forName(String className);
要求做异常处理
b、Class c = 对象的引用.getClass();
c、Class c=类名.class;
(2)针对操作获得相应的Method.Field.Constructor类型的对象或对象数组。
Field :set(所操作的对象应用,所更改的值/object)
fields[i].set()
Method: invoke(所操作对象的引用,参数所对应的对象数组);
methods[i]invoke(tom,new Object[]{“....”})
Constructor [] getParameterTypes()获得参数所在类型的所属的Class类型的对象所组成数组
newInstance(new Object[] {});
java.lang.reflect.*;
“任意”类的所有的方法声明
public static void main(String [] args)
chapter 07 Exception
1.异常:意外的情况。
class Exception
{
事件源:发生异常事件的主体对象。(Object)
事件描述:事件本身的相关信息。(String)
}
java中,异常是通过对象来描述,即异常对象。
当代码发生异常的时候,jvm将“自动创建”异常对象进行抛出
2.异常处理框架
子类类型的catch块一定在前,父类类型的在后,否则子类类型的catch将永远不能到达。
try
{
//怀疑可能发生问题的代码段
}
catch(ExceptionType2 e)
{
//对异常本身的处理
}
。。。。。。。。。。。
catch(ExceptionTypeN e)
{
//对异常本身的处理
}
catch(Exception e)
{
//对异常本身的处理
}
finally
{
//(1)不管异常是否发生,都必须执行
(2)专门用于处理“收尾”的工作;如关闭数据库,文件等
}
3.异常的内部原理:
(1)异常发生的时候,如果当前的方法没有处理该异常的框架,异常将会上抛到方法的调用处,以此类推,直到抛给jvm处理。
(2)一个方法发生异常,该方法的栈空间将被锁定,如果方法的嵌套调用复杂,建议主义栈区被连续锁定导致效率低下的风险。
main()
{
a();//抛给jvm
}
a()
{
b()
//锁定
}
b()
{
c()
}
c()
{
int a;//发生异常:该栈区被锁定(现场保护)
//发生异常
}
上抛过程。(方法嵌套数不能多于一定层)
4.
try:
catch:
finally:
throws:使用在方法的定义中,用于声明方法可能抛出的异常。
publicvoid method () throws
ExceptionType1,ExceptionType2。。。
调用一个声明抛出异常的方法,必须对该方法做异常处理
声明抛出异常的目的在于强制使用该方法的用户做异常处理。
(5).throw:手动的抛出一个异常对象
throw new Exception();
(匿名异常对象)
(无条件的转向语句 1. goto
2.三目运算符
3.main() throws Exception
效率低下 不建议使用的三条语句
)
5.自定义的异常类,,继承了异常类型
以便系统可以在发生异常的时候自动抛出
6.调试的时候推荐使用
getCause():getMessage();输出简单的导致异常的信息说明
printStackTrace():输出异常的栈信息
7.异常处理影响应用程序的效率,建议只在必要的时候使用
public static long currentTimeMillis();
8.对象的创建和异常之间的关系
当构造器抛出异常,对象的创建不成功,如果通过静态变量记录对象的个数,建议在catch()中对对象的个数做相应的减处理;
9.try ,catch,tinally和return的使用建议
(1).finally块中如果有return语句,下面的语句将不可以到达。
(2).建议不要在try,catch,finally块中使用return。try,catch块中的return可能是无效语句,被系统忽略。
(3)建议在存在finally块的时候,不要在catch中通过catch中通过throw再次的抛出异常对象,否则将很可能被系统作丢弃的处理。
10:断言:assert:
在开发过程中使用,用于在满足某种条件的情况下运行某些语句,不需要的时候可以关闭该功能
java -ea com.ch07.Exception
assert boolea-typed expression;
默认情况下断言功能关闭,在需要的时候可以在运行应用程序的时候打开。
assert 逻辑判断:”传入断言类型异常的构造器的参数“;
assert boolean-typed expression: string message to assertion facility
==========================================================================================================
GUI:图形用户界面
1.包 java.awt.*;java.awt.event.*; javax.swing.*;
2.容器:Container
顶极容器:不能再放入其他容器的容器
java中:JFrame:
setsize();
setVisible(boolean);是否可见
setTitle(String);
布局管理:组件或容器(中间)在容器中的排列方式
1.FlowLayout:流式布局
2.BorderLayout:边界布局:东南西北中的方式
3.GriderLayout:网格式布局:按行列的方式放置
4.CardLayout:卡式布局:类似于一组卡片的管理方式
JButton:按钮
JButton btn=new JButton("ok");
JTextField:文本框
JTextField text=new JTextField();
中间容器:可以将其放入其他容器的容器
JPanel:中间容器
JPanel p1=new JPanel(new FlowLayout(FlowLayout.RIGHT));
JPanel p2=new JPanel(new GridLayout(4,1,5,5));
事件处理:
添加监听:
事件处理方式的定义:
java.awt.event.*;
interface ActionListener{
public void actionPerformed(ActionEvent e);
//具体的事件处理
}
btn.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
//事件处理
}
});
=======================================================
(1)登录模块
* 用户验证,新用户注册
* JLabel lb1=new JLable("用户名");
* JPasswordField:密码输入框
* 大小是否可以改变
* void setResizable(boolean);
* //获得焦点的方法:
* public void grabFocus(){}
========================================================
gui2 :
1.事件处理模型:
"事件":java中,对象的状态(某个或某些属性值)的变化
1.事件类
class Event{
事件的主体:object(提供添加监听的相关方法来实现对事件源的观察)
对事件主体的描述:String
}
2.定义处理范围:监听器接口
事件处理范围的界定(规范,规则);interface
3.事件源所属的类
girl sad() happy()
4.测试类
删除监听的目的:如果对象被添加了监听,该对象在任何时候都不能被垃圾回收;即使已经变成了无用对象,建议,对于不再使用的事件处理删除监听以提高效率.
girl.add....Listener
Interface MouseMotionListener{
void mouseDragged(MouseEvent e)
void mouseMoved(MouseEvent e)
}
2.排号系统:
1.vip
if(flag&&vipData.size>0)
if(!flag&&vipData.size>=3)
2.norm
if(!flag&&vipData.size<=3&&normData.size>0)
//生产各种信息框
class SubFrame{
}
Gui3:
1. 菜单:
JMenuBar:菜单条
JMenu:菜单
JMenuItem:菜单项
2.单选按钮和复选按钮
单选:JRadioButton
ButtonGroup:"逻辑"分组
JRadioButton rb1=new JRadioButton("男");
JRadioButton rb2=new JRadioButton("女");
ButtonGroup bg=new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
JPanel p=new JPanel(new FlowLayout())
p.add(rb1);
p.add(rb2);
//p.add(bg); 这种是把他们物理上捆在一起. 所以用上面的 添加
复选:JCheckBox
1.时间
start();启动
stop():终止
Timer timer=new Timer(时间间隔(毫秒),new ActionLiatener(){
public void actionPerformed(ActionEvent e){
}
});
class test implements ActionListener{
private Timer timer=new Timer(1000,this);
public void actionPerformed(ActionEvent e){
if(e.getSource()==timer){
}
}
}
timeLbl=new JLabel("20");
String str=timeLbl.getText();
try{
int value=Integer.ParseInt(str);
value--;
if(value==0){
}
timeLbl.setText(value
}cath(Exceptioon e){
}
2.随机数
boolean flag;
flag=false;
flag=true;
产生新的随机数:
flag=false;
/*
*1.小学生的考试系统
* (1)登录模块
* 用户验证,新用户注册
* JLabel lb1=new JLable("用户名");
* JPasswordField:密码输入框
* 大小是否可以改变
* void setResizable(boolean);
* //获得焦点的方法:
* public void grabFocus(){}
* (2)考试模块
1.要求有时间限制;
提前提示考试时间即将结束!
如果考试结束,显示当前考生的信息
2.只能做100以内的整数的加减乘除(0-100)
算法: String[] oper={"+","-","*","/"}
0<(int)(Math.random()*4)<=3
public void getProblem(){
int index=(int)(Math.random()*4);
int[] number=getNumber(index);
}
public int[] getName(int index){
switch(index){
case 0:{
}break;
case 1:{
}break;
case 2:{
}break;
case 3:{
}break;
}
}
3.要求提供前翻,后翻的检查功能.
4.要求提交之后输出分数.
*
*/
13.Threads 多线程:
1.进程:os(操作系统)表示一个完整的任务,可以由很多应用程序组成(协同工作)
java:一个应用程序
2.线程:单一的程序控制流,比进程的单位要小,程序运行的最小单位(不能再分割),并且可以独立运行,互相之间不受影响的小任务.
3.比较:
数据:
进程的地址空间相对独立
线程的地址空间共享
cpu时间:("同一段时间")
每一个进程、线程都有独立的cpu时间
代码:任务本身的描述
进程、线程可以共享
java.lang.Thread(线程类)
*currentThread():获得当前线程的引用.
getName():获得当前线程的名字
setName(String s):设置当前线程的名字
sleep(int):让一个线程暂时挂起一段时间(毫秒), 要求做异常处理(可能在挂起的时候被唤醒)
isAlive():判断一个线程是否进入死亡状态
setPriority(int): 设置线程的优先级
getPriority():
join():一个线程等待另外一个线程结束之后再结束
线程通信:
wait():使线程进入等待状态
notify():唤醒一个线程
notifyAll():唤醒所以线程
1.都来自Object类
class Object{
equals(){}
toString(){}
hashCode(){}
wait(){}
notify(){}
notifyAll(){}
}
2.都必须用在同步方法中(synchronized修饰的方法)
3.通常结合统一的标记去使用,flag( 建议多种状态使用数字);
main()--主线程
其他的线程可以叫子线程,都由主线程产生.
三、创建子线程的方式:
1。继承Thread类
class Test extends Thraed{
//定义线程所执行的任务
public void run(){
}
}
start(){
}//启动一个线程
stop();停止一个线程(禁止使用,容易导致异常)
2。实现Runnable接口
通常在实现多线程的同时去继承一个类的时候使用,两种方法可以任意选择,没有效率上的差别
class Test implements Runnable{
//定义线程所执行的任务
public void run(){
}
}
需要自己构造线程对象
Thread t=new Thread(Runnable);
t.start();
method()----在代码区中有多少个?
方法名表示方法所对应的指令在代码区的地址,
class Oper extends thread{
private
public Oper(Account account,String operType){
this.....
this
}
public void run(){
if(...){
}
}
public void 存款(){
}
public void 取款(){
}
}
join():
如果A线程等待B线程结束之后再结束,在A的代码中去调用B线程的Join()方法,即谁等待,就去谁的代码中调用,等待谁,就调用谁的join()方法。
4.并发访问控制:
1.synchronized 修饰的方法称为同步方法,当一个线程调用了一个对象的同步方法的时候,该线程有机会获得对象的锁,获得了对象的锁之后,就可以保证该线程对对象操作的完整性。synchronized
2.同步块:
当线程所操作的对象所属的类没有同步方法,且又不方便对该类作源码的修改的时候,可以选择同步块来实现线程的同步。
synchronized(线程所操作的对象的引用) {
//线程对对象的操作
}
锁池:内存区
3.生产者和消费者的问题.
线程之间的通信问题。
作业:
帐户的管理系统
1.两个操作界面 1.ATM (多个)
帐号,和密码进行验证。
存款 、取款、 查询功能
class Account{
private double value;
private String accountId;
private User user;
synchronized public void operMethod(double value){
}
}
2.管理员(一个) (1)实时的监控取款机的余额情况,如果到警戒余额的时候,自动弹出警告.
(2)统计功能 要求通过"日志"统计
(3)用户的验证经历加密和解密过程。
class ATM{
log.write(..);
}
//日志
import java.util.*;
class Log{
private List list=new LinkedList();
//private Set set=new HashSet();
//private String logContent;
public void write(String logContent){
list.add(logContent);
}
public void print(){
Iterator iter=list.iterator();
while(iter.hasNext()){
System.out.println(iter.next());
}
}
}
4.死锁:逻辑异常。
线程之间的资源的冲突问题
由于线程占用对象的锁,且因为某种原因永远无法释放,等待该对象的锁的线程将会永远等待下去使应用程序停止
package com.briup.md13;
class A{
synchronized public void methodA(B b) {
Thread t=Thread.currentThread();
System.out.println(t.getName()+"in the methodA()");
try{
t.sleep(400);
}catch (Exception e) {
e.printStackTrace();
}
System.out.println(t.getName()+"will call the last() of a");
b.last();
}
synchronized public void last() {
System.out.println("in the last if A");
}
}
class B{
synchronized public void methodB(A a) {
Thread t=Thread.currentThread();
System.out.println(t.getName()+"in the methodB()");
try{
t.sleep(300);
}catch (Exception e) {
e.printStackTrace();
}
System.out.println(t.getName()+"will call the last() of B");
a.last();
}
synchronized public void last() {
System.out.println("in the last if B");
}
}
public class DeadLockTest implements Runnable{
private A a=new A();
private B b=new B();
public DeadLockTest(){
a.methodA(b);
(new Thread(this)).start();
}
/*
*(1)子线程启动----》b.method(a);子线程占有b的锁
同时:主线程-》a.method(b);主线程占有a的锁
* (2)调用last()方法的时候:
子线程:---》a.last()方法,成功调用的条件:子线程占有a的锁。当前a的锁被主线程占用,没有释放。释放条件所时间(1)中,a.methodA(b)执行完毕
主线程:---b.last(),主线程希望获得b的锁,b的锁当前被子线程占用,b.methodB()执行完毕将释放b的锁。
解决方法:
建议方式:调整时间差,代码的先后顺序。
如果时间差无法解决,再去调用整个线程所占有的资源(对象的锁)。
*/
public void run() {
b.methodB(a);
}
public static void main(String[] args) {
new DeadLockTest();
}
}
5。线程的启动和终止;
class Test implements Runnable{
private boolean flag;
private Thread t;
public Test(){
t=new Thread(this);
}
public void start(){
flag=true;
t.start();
}
public void run(){
while(flag){
}
//if(flag){
}
}
public void stop(){
flag=false;
}
}
线程的优先级:不建议去手动设置
setProiority(int )
14 IO
1.流:stream
字节的"源"或"目的(地)"
输出设备,输入设备;
分类:输入流,输出流
字节流,字符流
3.关闭输出流之前建议清除缓存
flush()
清除缓存,缓冲区
4.字节流
(1)BufferedInputStream/BufferedOutputStream
专门用于对InputStream/OutputStream的子类进行包装,用于提高传输的效率
(2)DataInputStream/DataOutputStream
字节流的基础上做基本数据类型的包装,在处理基本数据类型的数据的时候选择使用.
int: int readInt();读 writeInt(int);写
float: readFloat() writeFloat(float);
(3)PipedInputStream/PipedOutputStream
管道输入输出流,通常用于处理多线程的输入输出操作
5,字符流
(1)InputStreamReader/OutputStreamWriter
字节流和字符流之间的转换桥梁桥梁
(2)BufferedReader/BufferedWriter:
专门用于提高效率,对Reader和Writer的子类进行包装
6.文件
fileInputStream/fileOutputStream
fileInputStream: 将文件包装成输入设备
fileOutputStream:将文件包装成输出设备,如果作为输出设备的文件不存在,将会自动创建一个新的文件,
要求: 总能产生(任意多个)唯一的id, id自动的增长
7.多线程拷贝:
public class CopyThread implements Runnable{
private int start,end;
private String fileName;
public CopyThread(String fileName,int start,int end){
}
public void run(){
write(read());
}
//写文件(特定位置)
private void write(){
}
//从文件的指定位置读出内容
private String(byte[]) read(){
}
}
8.对象的序列化:对象状态的保存,
反序列化:将文件中保存的对象的状态还原成应用程序中的对象.
Serializable:序列化接口,只起到说明的作用,说明实现该接口的类的对象可以被序列化.
class User implements Serializable{
}
transient :禁止某个属性被序列化
class Userservice{
private static Set set=new HashSet();
//缓存:通过某些方式保持缓存中的数据和外部介质的数据的一致性
private int count;//操作次数
static {
}
public static void add(User user){
count++;
}
public static void updata(User user){
count++;
}
public static void remove(User user){
count++;
}
//涉及多个重载的方法
public static void findUser(){
}
}
gui/web:表示层
UserService:业务逻辑层
文件:数据层
由上至下:依赖关系
由下至上:完全的低耦合的关系
分层开发的要求:对任何一层中的方法实现的改变都不会影响到其他层次的正常工作.
1.
public void findUser(int start,int end,String type){
Set set1=TreeSet();
List list=new ArrayList();
int count=0;
Iterator iter1=set1.iterator();
while(iter1.hasNext()){
list.add(iter1.next());
}
if(start>end){}
if(start==end){}
if(end>list.size()){}
if(start<1){
start=1;
}
List subList=new ArrayList();
Iterator iter2=set1.iterator();
while(iter2.hasNext()){
list.add(iter2.next());
}
for(int i=start-1;i<end;i++){
subList.add(list.get(i));
}
return sublist;
}
2.
public void findUser(int start,int end,String type){
Set set1=TreeSet();
//User[] user=new User[end-start];
int count=0;
Iterator iter=set1.iterator();
while(iter.hasNext()){
list.add(iter.next());
}
get(start-1);
.
.
get(end-1);
}
netWork:
1.协议:软件,公共的规范
(1)tcp/ip:有保障的
public Socket("ip地址",端口号);
public Socket("127.0.0.1",端口号);---->与本机通信
1.Socket:包装了发送和接受功能的"通信端点"的类
2.通信的信息:ip地址,端口号
3.ServerSocket:服务器端
ServerSocket ss=new ServerSocket(8888);
Socket socket=ss.accept();
4.发送和接收功能的实现:
InputStream is=Socket.getInputStream();
OutputStream os=Socket.getOutputStream();
(new java.util.Date()).toString();
PrintWrite
(2)udp:无保障的通信协议,大量数据的采样
1.DatagramSocket:UDp协议的通信端点
new DatagramSocket(8888);
new DatagramSocket();
2.DatagramSocket:数据包
信封:信的内容及地址 发送的时候
DatagramSocket outPacket=new DatagramSocket(byte[],int length,new InetSocketAddress("ip",port));
socket.send(outPacket);
接收:
DatagramSocket inPacket=new DatagramSocket(byte [],int length);
socket.receive(inPacket);
Client :
将new InetSocketAddress("ip",port);对象包装在outPacket中
server:
inPacket.getSocketAddress(); 获得客户端地址信息
class Chat{
public void actionPerformed(ActionEvent e){
if(e.getSource()==sendBtn||e.getSource()==sendText){
}
if(...){}
}
public class Receiver implements Runnable{
public Receiver(){
(new Thread(this)).start();
}
public void run(){
while(true){
//接受
}
}
}
}
浙公网安备 33010602011771号