您好,欢迎访问三七文档
Java的回调机制模块之间总是存在着一定的接口,从调用方式上来看,可以分为三类:同步调用、回调和异步调用。同步调用时一种阻塞式调用,也是我们在写程序时经常使用的;回调时一种双向的调用模式,也就是说被调用的接口被调用时也会调用对方的接口;异步调用是一种类似消息或事件的机制,解决了同步阻塞问题,举例来说:A通知B后,它们各走各的互不影响,不想同步调用那种,A通知B后,非等到B走完后,A才继续走。回调时异步的基本。那回调机制为什么会出现呢?在我们现实生活中,有如下这样场景:有一位老板很忙,他没有时间盯着员工干活,然后他告诉自己的雇员,干完当前这些事情后,告诉他干活的结果。这个例子其实是一个回调+异步的例子,再举一个例子,A程序员写了一段程序a,其中预留了回调函数接口,并封装好了该程序,程序员B让a调用自己的程序b中的一个方法,于是,他通过a中的接口回调自己b中的方法,到这里你可能似懂非懂了,后面会继续说明回调的出现原因。接下来我们把上面例子变成代码,看到网上很多人最后搞混了异步和回调,因此例子中不加入异步调用。(注意:回调可不是解决什么调用时间过长问题,那是异步!)首先创建一个回调接口,老板的告知干活完如何找到他的方式,留下老板的办公室地址:packagecom.callback;/***此接口为联系的方式,不论是电话号码还是联系地址,作为老板都必须要实现此接口*@authorAdministrator**/publicinterfaceCallBackInterface{publicvoidexecute();}packagecom.callback;/***创建回调对象,就是老板本人**老板是作为上层应用设分出现的,下层应用(员工)是不知道有哪些方法,因此他想被下层应用(员工)*调用必须实现接口*@authorAdministrator**/publicclassBossimplementsCallBackInterface{@Overridepublicvoidexecute(){//TODOAuto-generatedmethodstubSystem.out.println(收到了!!+System.currentTimeMillis());}}packagecom.callback;/***员工类,必须记住,这是一个底层类,底层是不了解上层服务的*@authorAdministrator**/publicclassEmployee{privateCallBackInterfacecallBack=null;//告诉老板的联系方式,也就是注册publicvoidsetCallBack(CallBackInterfacecallBack){this.callBack=callBack;}//工人干活publicvoiddoSome(){//1.开始干活了for(inti=0;i10;i++){System.out.println(第【+i+】事情干完了!);}//2.告诉老板或干完了callBack.execute();}}packagecom.callback;publicclassClient{publicstaticvoidmain(String[]args){//TODOAuto-generatedmethodstubEmployeeemp=newEmployee();//将回调对象(上层对象)传入,注册emp.setCallBack(newBoss());//开启控制器对象运行emp.doSome();}}Java的串行虚拟化(Serialization)一、串行化的概念和目的1、什么是串行化对象的寿命通常随着生成该对象的程序的终止而终止。有时候,可能需要将对象的状态保存下来,在需要时再将对象恢复。我们把对象的这种能记录自己的状态以便将来再生的能力。叫作对象的持续性(persistence)。对象通过写出描述自己状态的数值来记录自己,这个过程叫对象的串行化(Serialization)。串行化的主要任务是写出对象实例变量的数值。如果交量是另一对象的引用,则引用的对象也要串行化。这个过程是递归的,串行化可能要涉及一个复杂树结构的单行化,包括原有对象、对象的对象、对象的对象的对象等等。对象所有权的层次结构称为图表(graph)。2、串行化得目的Java对象的单行化的目标是为Java的运行环境提供一组特性,如下所示:1)尽量保持对象串行化的简单扼要,但要提供一种途径使其可根据开发者的要求进行扩展或定制。2)串行化机制应严格遵守Java的对象模型。对象的串行化状态中应该存有所有的关于种类的安全特性的信息。3)对象的串行化机制应支持Java的对象持续性。4)对象的串行化机制应有足够的可扩展能力以支持对象的远程方法调用(RMI)。5)对象串行化应允许对象定义自身的格式即其自身的数据流表示形式,可外部化接口来完成这项功能。二、串行化的方法从JDK1.1开始,Java语言提供了对象串行化机制,在java.io包中,接口Serialization用来作为实现对象串行化的工具,只有实现了Serialization的类的对象才可以被串行化。Serializable接口中没有任何的方法。当一个类声明要实现Serializable接口时,只是表明该类参加串行化协议,而不需要实现任何特殊的方法。下面我们通过实例介绍如何对对象进行串行化。1、定义一个可串行化的对象一个类要使其对象可以被串行化,必须实现Serializable接口。我们定义一个Student如下:PublicclassStudentimplementsSerializable{Intid;Stringname;Intage;Stringdepartment;PublicStudent(intid,Stringname,intage,Stringdepartment){this.id=id;this.name=name;this.age=age;this.department=department;}}2、构造对象的输入、输出流要串行化一个对象,必须与一定的输入输出流联系起来,通过对象的输出流将对象的状态保存下来,在通过对象的输入流将对象状态恢复。java.io包中,提供了ObjectInputStream和ObjectOutputStream将数据流功能扩展至可读写对象。在ObjectInputStream中用readObject()方法可以直接读取一个对象,ObjectOutputStream中用writeObject()方法可以直接将对象保存到输出流中。PublicclassObjectSer{Publicstaticvoidmain(Stringargs[])throwsIOException,ClassNotFoundException{Studentstu=newStudent(981036,”Liuming”,18,”CSD”);FileOutputStreamfo=newFileOutputStream(“data.ser”);ObjectOutputStreamso=newObejctOutputStream(fo);Try{So.witeobject(stu);So.close();}catch(IOExceptione){}Stu=null;FileInputStreamfi=newFileInputStream(data.ser);ObjectInputStreamsi=newObjectInputStream(fi);try{stu=(Student)si.readObject();si.close();}catch(IOExceptione){System.out.println(e);}System.out.println(StudentInfo:);System.out.println(ID:+stu.id);System.out.println(Name:+stu.name);System.out.println(Age:+stu.age);System.out.println(Dep:+stu.department);}}在这个例子中,我们首先定义了一个类Student,实现了Serializable接口,然后通过对象输出流的writeObject()方法将Student对象保存到文件data.ser中。之后,通过对家输入流的readObjcet()方法从文件data.ser中读出保存下来的Student对象。从运行结果可以看到,通过串行化机制,可以正确地保存和恢复对象的状态。三、串行化的注意事项1、串行化能保存的元素串行化只能保存对象的非静态成员交量,不能保存任何的成员方法和静态的成员变量,而且串行化保存的只是变量的值,对于变量的任何修饰符都不能保存。2、transient关键字对于某些类型的对象,其状态是瞬时的,这样的对象是无法保存其状态的。例如一个Thread对象或一个FileInputStream对象,对于这些字段,我们必须用transient关键字标明,否则编译器将报措。另外,串行化可能涉及将对象存放到磁盘上或在网络上发达数据,这时候就会产生安全问题。因为数据位于Java运行环境之外,不在Java安全机制的控制之中。对于这些需要保密的字段,不应保存在永久介质中,或者不应简单地不加处理地保存下来,为了保证安全性。应该在这些字段前加上transient关键字。Java的synchronizedJava语言的关键字,可用来给对象和方法或者代码块加锁,当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这个段代码。当两个并发线程访问同一个对象object中的这个加锁同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。然而,当一个线程访问object的一个加锁代码块时,另一个线程仍然可以访问该object中的非加锁代码块。一、Synchronized方法1、方法声明时使用,放在范围操作符(public等)之后,返回类型声明(void等)之前。这时,线程获得是成员锁,即一次只能有一个线程进入该方法,其它线程要想在此时调用该方法,只能排队等候当前线程执行完后,别的线程才能进入。Eg:PublicsynchronizedvoidsynMethod(){//方法体}2、对某一代码块使用,synchronized后面跟括号,括号里是变量,这样,一次只有一个线程进入该代码快,此时,线程获得是成员锁。PublicintsynMethod(inta1){Synchronized(a1){//一次只有一个线程进入}}二、理解一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。二、然而,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。四、第三个例子同样适用其它同步代码块,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。五、以上规则对其它对象锁同样适用。Java的泛型(generics)Eg:用泛型方法打印出不同字符串的元素PublicclassGenericMethodTest{//泛型方法printArrayPublicstaticEvoidprintArray(E[]inputArray){//输出数组元素For(Eelement:inputArray){Sysout(“%S”,element);}}Publicstaticvoidm
本文标题:爪哇不眠夜
链接地址:https://www.777doc.com/doc-2219956 .html