徐州开发的网站,app网站开发成功案例,网站新闻标题标题怎样进行优化,兽装全身定制大概价格1、JAVA 2、计算机网络 3、计算机体系结构 4、数据库 5、计算机租场原理 6、软件工程 7、大数据 8、英文 自我介绍
1. Java
1. 和 equals的区别
比较基本数据类型是比较的值#xff0c;引用数据类型是比较两个是不是同一个对象#xff0c;也就是引用是否指向同 一个对象 和 equals的区别
比较基本数据类型是比较的值引用数据类型是比较两个是不是同一个对象也就是引用是否指向同 一个对象地址是否相同equals本质上也是但是可以重写这个方法比如String和Integer类。
2. 为什么重写equals要重写hashcode
我个人的理解是Hash比equals方法的开销要小速度更快所以在涉及到hashcode的容器中比如 HashSet判断自己是否持有该对象时会先检查hashCode是否相等如果hashCode不相等就会 直接认为不相等并存入容器中不会再调用equals进行比较。而hashcode的默认方法是根据内存地 址获得的这样就会导致即使该对象已经存在HashSet中但是因为hashCode不同还会再次被存 入。 因此要重写hashCode保证如果equals判断是相等的那hashCode值也要相等。
3. 什么是拆箱和装箱
我理解的就是基本类型和包装类型的相互转换: 装箱就是基本数据类型可以直接赋值给包装类型也就是Object变量 拆箱就是包装类型也可以自动转化为基本数据类型进行赋值或者比较
4. final类有什么特点
不可以被继承final修饰的方法不可被重写final修饰的变量基本数据类型值不可修改引用数据类型指向不可发生变化
5.谈谈final、finally和finalize的区别
final是修饰成员变量、类、方法表示不可再改变 finally是处理异常的关键字表示最后执行 finalize是Object类的一个方法在垃圾收集器执行的时候会执行被回收对象的这个方法可以覆 盖此方法提供垃圾收集时的其他资源回收例如文件关闭 等等。
6.垃圾回收
GC是什么为什么要有GC GC时垃圾收集的意思Gabage Collection。内存处理是开发人员容易出现问题的地方忘记或者错误 地内存回收会导致程序或者系统的不稳定甚至崩溃Java提供的垃圾回收机制可以自动检测对象是否超 过作用域从而达到自动回收的目的。垃圾回收机制 Java垃圾回收机制不需要显示的去释放一个对象的内存而是由JVM自动机型管理。在Jvm中有一个 低优先级的垃圾回收线程。在正常情况下是不会执行的只有在虚拟机空闲时或者堆内存不足时会触 发执行扫描那些没有被任何引用的对象将它们添加到要回收的集合中然后进行回收操作。如何判断一个对象是否存活GC对象的判断方法 1、 引用计数法给每一个对象都设置一个引用计数器当有一个地方引用这个对象时则 count1引用失效时count-1当count0时说明此对象没有被其他对象引用也就是死 对象。将会被GC回收。 简单但会出现循环引用即: A引用BB引用A。 2、可达性分析GC_roots作为对象的起始点从这些节点开始向下搜索走过的路径称为引用链 当一个对象到 GC Roots 没有任何引用链相连时则证明此对象不可用的
上图中Object1~Object4都可以被GC Root访问到而Object5~Object7都不可以被访问到这也就是说。也就是说Object5、6、7这三个对象就是不可达的下次垃圾回收的时候可能就会被回收掉。 其实并不是所有的对象都可以作为GC Roots的对象只有下列的对象可以作为GC Roots的对象。
虚拟机栈栈帧中的本地变量表中引用的对象方法区中类静态属性引用的对象方法区中常量引用的对象本地方法栈中JNI即一般说的Native方法引用的对象
既然是引用计数法那肯定就有各种引用下面来说说一些引用。
引用指在程序代码之中普遍存在的类似 Object obj new Object() 这类的引用只要强 引用还存在垃圾收集器永远不会回收被引用的对象软引用用来描述一些还有用但并非必需的对象。对于软引用关联着的对象在系统将要发生内存 溢出异常之前将会把这些对象列进回收范围之中进行第二次回收。如果这次回收还没有足够的内存才会抛出内存溢出异常。在JDK1.2之后提供了SoftReference类来实现软引用弱引用用来描述非必需对象但是他的强度比软引用更弱一些被弱引用关联的对象只能生存到下一次垃圾收集之前。当垃圾收集器工作时无论当前内存是否足够都会回收掉只被弱引用关联的对象。在JDK1.2之后提供了WeakReference类来实现弱引用虚引用也被称为幽灵引用或者幻影引用。它是最弱的一种引用关系。一个对象是否有虚引用的存在完全不会对其生存时间构成影响也无法通过虚引用来取得一个对象实例。为一个对象设置虚引用关联的唯一目的就是能在这个对象被收集器回收时收到一个系统通知。在JDK1.2之后提供了PhantomReference类来实现虚引用。供对象被finalize之后执行指定的逻辑的机制cleaner)
7. 关键字native
一个Native Method就是一个java调用非java代码的接口。这个接口写在java中实现方式是用其他语 言eg: C或C native不可与abstract一起使用可以重写。 可以将native方法比作Java程序同程序的接口其实现步骤
1、在Java中声明native()方法然后编译 用javah产生一个.h文件 写一个.cpp文件实现native导出方法其中需要包含第二步产生的.h文件注意其中又包含了JDK 带的jni.h文件 将第三步的.cpp文件编译成动态链接库文件 在Java中用System.loadLibrary()方法加载第四步产生的动态链接库文件这个native()方法就可以 在Java中被访问了
6、集合
Set如何区分重复与否 使用equals而不是当向集合Set中增加对象时首先集合计算要增加对象的hashCode码根据该值来得到 一个位置用来存放当前对象。 如果在该位置没有一个对象存在的话那么集合Set认为该对象在集合中不存在直接 增加进去。 如果在该位置有一个对象存在的话接着将准备增加到集合中的对象与该位置上的对象 进行equals方法比较。 如果该equals方法返回false那么集合认为集合中不存在该对象再进行一次散列 将该对象放到散列后计算出来的地址中。 如果equals方法返回true那么集合认为集合中已经存在该对象了不再将该对象增加到集合中。重写equals方法的时候必须重写hashCode方法。如果一个类的两个对象使用equals 方法比较时结果为true,那么这两个对象具有相同的hashCode。原因是equals方法为true,表明是同一个对象它们hashCode当然相同。(Object类的equals方法比较的是地址)Object类的hashCode方法返回的是Object对象的内存地址。我们可以通 Integer.toHexString(newObject().hashCode());来得到。Java里面的HashSet中如何判断两个对象是否相等 先hashcode如果相等则用equals因为hashcode快。判断两个对象的hashCode是否相等。 如果不相等认为两个对象不相等。完毕 如果相等转入2判断两个对象是否equals 如果不相等认为两个对象不相等。 如果相等认为两个对象相等。数组和集合的区别 数组存放基本数据类型和对象引用集合类存放对象的引用。 数组长度无法动态改变集合可以 数组无法判断实际大小只有长度集合有.size()方法 集合以类的方式存在具有封装继承多态的特性。 ★ 4. Java集合类框架的基本接口有哪些 Collection和Map两个接口元素集合和键值对集合。 List和Set接口继承Collection接口 HashMap和HashTable实现了Map接口HashTable线程安全。 上述类图中实线边框的是实现类比如ArrayListLinkedListHashMap等折线边框的是抽象 类比如AbstractCollectionAbstractListAbstractMap等而点线边框的是接口比如 CollectionIteratorList等。说说 List,Set,Map 三者的区别 List (对付顺序的好帮⼿) 存储的元素是有序的、可重复的。 Set (注重独⼀⽆⼆的性质): 存储的元素是无序的、不可重复的。 Map (⽤ Key 来搜索的专家): 使⽤键值对kye-value存储类似于数学上的函数 yf(x)“x”代 表 keyy代表 valueKey 是⽆序的、不可重复的value 是⽆序的、可重复的每个键最多映 射到⼀个值。什么是迭代器 Iterator是一种遍历集合类元素的对象提供了一种通用的访问集合元素的方法无需知道集合内部的 结构和实现细节。迭代器以内部类的形式存在每个集合类中。无法逆向访问元素, 在使用迭代器遍历集 合时不能在集合中添加或删除元素 常用方法 hasNext() 判断是否还有下一个元素。 next() 返回下一个元素并将迭代器的位置向后移动。 remove() 从集合中删除迭代器返回的最后一个元素。 使用迭代器访问ArrayList: import java.util.; public class Test{ public static void main(String[] args) { List listnew ArrayList(); list.add(“Hello”); list.add(“World”); list.add(“HAHAHAHA”); //第一种遍历方法使用foreach遍历List for (String str : list) { //也可以改写for(int i0;ilist.size();i)这种形式 System.out.println(str); } //第二种遍历把链表变为数组相关的内容进行遍历 String[] strArraynew String[list.size()]; list.toArray(strArray); for(int i0;istrArray.length;i) //这里也可以改写为 foreach(String str:strArray)这种形式 { System.out.println(strArray[i]); } //第三种遍历 使用迭代器进行相关遍历 Iterator itelist.iterator(); while(ite.hasNext())//判断下一个元素之后有值 { System.out.println(ite.next()); } } } 遍历Map import java.util.; public class Test{ public static void main(String[] args) { MapString, String map new HashMapString, String(); map.put(“1”, “value1”); map.put(“2”, “value2”); map.put(“3”, “value3”); //第一种普遍使用二次取值 System.out.println(“通过Map.keySet遍历key和value”); for (String key : map.keySet()) { System.out.println(key key and value map.get(key)); } //第二种 System.out.println(“通过Map.entrySet使用iterator遍历key和value”); IteratorMap.EntryString, String it map.entrySet().iterator(); while (it.hasNext()) { Map.EntryString, String entry it.next();Iterator和ListIterator的区别 Iterator 和 ListIterator 是Java中两种不同的迭代器实现它们都用于遍历集合元素但在功能上 有一些区别。Iterator 能用于遍历List、Set、Map等集合类的元素而 ListIterator 只能用于遍历List集合 的元素。因此如果要遍历Set或Map等集合只能使用 Iterator 而不能使用 ListIterator 。Iterator 只支持向前遍历集合元素而 ListIterator 支持向前和向后遍历集合元素可以使用 previous() 方法获取前一个元素。因此如果需要对List集合进行双向遍历可以使用 ListIterator 而不能使用 Iterator 。ListIterator 相对于 Iterator 增加了一些额外的方法如 add() 、 set() 、 hasPrevious() 、 previousIndex() 、 nextIndex() 等可以在遍历过程中对集合元素进行插 入、修改、删除等操作。而 Iterator 只有 remove() 方法只能用于删除集合元素不能进行插 入、修改等操作。 System.out.println(key entry.getKey() and value entry.getValue()); } //第三种推荐尤其是容量大时 System.out.println(“通过Map.entrySet遍历key和value”); for (Map.EntryString, String entry : map.entrySet()) { System.out.println(key entry.getKey() and value entry.getValue()); } //第四种 System.out.println(“通过Map.values()遍历所有的value但不能遍历key”); for (String v : map.values()) { System.out.println(value v); } } } import java.util.ArrayList; import java.util.ListIterator; public class Main { public static void main(String[] args) { ArrayList list new ArrayList(); list.add(“Java”); list.add(“Python”); list.add(“C”); // 使用ListIterator遍历List集合 ListIterator iterator list.listIterator(); while (iterator.hasNext()) { String item iterator.next(); System.out.println(item); // 对集合元素进行修改和插入操作 if (item.equals(“Java”)) { iterator.set(“Java SE”);Java中的HashMap的工作原理 实现了Map接口以键值对的形式存储数据。 HashMap需要哈希函数对key计算hash值使用对象的hashcode和equals方法来进行存取。 不可有重复的键重复的充要条件是equals返回true。 11.HashMap实现方式 数组链表红黑树 当链表长度大于 8 时我们会对链表进行“树化”操作将其转换成一颗红黑树一种二叉树左边节点 的值小于根节点右边节点的值大于根节点 HashMap:上面也说了HashMap 的底层实现是数组链表红黑树的形式的同时它的数组的默认初 始容量是16、扩容因子为0.75每次采用2 倍的扩容。 也就是说每当我们数组中的存储容量达到75% 的时候就需要对数组容量进行2 倍的扩容。 iterator.add(“Java ME”); } } // 再次使用ListIterator遍历List集合 System.out.println(“修改后的List集合”); iterator list.listIterator(); while (iterator.hasNext()) { String item iterator.next(); System.out.println(item); } } } Java Python C 修改后的List集合 Java SE Java ME Python Cerror 和 exception的区别 这两个我理解的是错误和异常都是Throwable的子类Error更加严重 Exception是程序正常运行中可以预料到的意外情况可以捕获进行相应处理。 可检测异常编译检查的部分要不然编译不通过 不可检测异常eg Error在正常运行中不太可能出现的情况。绝大部分的Error 都会导致程序处于非正常的,不可恢 复的状态, 不需要捕获, 常见的OutOfMemoryError 是Error的子类.abstract的method是否可同时是static是否可同时 是native否可同时是synchronized不可是static之类需要被实现static和子类没有关系不可是nativenative方法表示该方法需要用另一种依赖平台的编程语言实现不存在子类被实现 问题。synchronized 是同步然而同步是需要有具体操作才能同步的如果像abstract只有方法声明 那同步一些什么东西就会成为一个问题了当然抽象方法在被子类继承以后可以添加同步。接口是否可继承接口抽象类是否可实现接口抽象类 是否可继承实现类 我认为 接口可以继承接口 抽象类可以实现接口 抽象类可以继承实现类但前提是实现类必须有明确的构造函数。 12.try中的returnfinally会不会执行return前还是 return后 会执行会在return 前执行。 The finally block always executes when the try block exits. 当尝试块退出时最终块总是执行。try中有return, 会先将值暂存无论finally语句中对该值做什么处理最终返回的都是try语句中的 暂存值。当try与finally语句中均有return语句会忽略try中return。 package top.yanzx; /**Author: yanzxDate: 2023/2/27 14:26Description:int 和 Integer有什么区别 int是基本数据类型integer是引用数据类型是int的包装类。八大基本类型都有相应的包装类。描述一个JVM加载class文件的原理机制、 简答: JVM中类的加载是由classloader和它的子类来实现的 java classloader是一个重要的java运行系 统组件它负责查找和装入类文件的类。 JVMJava Virtual Machine是一个运行Java程序的虚拟机它负责将Java程序的字节码文件加载到内 存中并执行这些字节码指令。下面是JVM加载class文件的基本原理机制类加载器JVM中的类加载器ClassLoader负责加载Java类文件到内存中。ClassLoader可以从 文件系统、网络或其他来源中加载class文件。类加载过程当JVM需要一个类时它会先请求ClassLoader将类加载到内存中。ClassLoader会 根据类的全限定名Fully Qualified Name查找相应的class文件如果找到则加载这个class文 件否则抛出ClassNotFoundException异常。类加载阶段类加载器加载class文件时会经历以下3个阶段 (1) Loading加载阶段在这个阶段类加载器将class文件中的二进制数据读入到内存中并 创建一个对应的Class对象。 (2) Linking连接阶段在这个阶段类加载器会执行以下操作 */ public class Demo04Try { public static void main(String[] args) { System.out.println(func1()); } public static int func1(){ int x 1; try { // 返回的暂存值return会暂存x的值finally也会执行但修改的值和返回的值无 关。 return x; }finally { x 1 ; System.out.println(x); } } } a. 验证验证class文件的正确性包括字节码格式、符号引用等方面的验证。 b. 准备为类的静态变量分配内存并初始化为默认值。 c. 解析将类中的符号引用转化为直接引用即将类、方法、变量等符号解析为内存地址。 (3) Initialization初始化阶段在这个阶段类的静态变量和静态代码块会被执行完成类的 初始化。类加载器的层次结构JVM中的类加载器形成了一个层次结构ClassLoader可以有多个每个 ClassLoader都有自己的父ClassLoader。当一个类需要被加载时JVM会先从最上层的 ClassLoader开始查找如果找不到则向下逐级查找直到找到为止。类的生命周期类的生命周期包括加载、验证、准备、解析、初始化、使用和卸载等阶段。JVM中 的类加载器和类的生命周期是密切相关的ClassLoader负责加载、验证、准备、解析和卸载 类而类的初始化和使用则由JVM负责。封装具有的特性 封装的作用是对象外部不能随意存取对象的内部数据避免外部错误。只提供少量接口对内部成员变量 进行操作因此大大减少了内部的修改对外部的影响。 特性 数据吟唱 接口访问 实现隔离 可维护性 重用性 封装Encapsulation是面向对象编程中的一种重要概念它指的是将数据和方法包装在一个类中 隐藏实现细节仅向外界提供有限的访问接口从而实现数据的安全性、可靠性和易用性。封装具有以 下特性数据隐藏封装将类的数据和方法封装在一起对外部世界屏蔽了内部的实现细节只提供有限的 访问接口。这样可以保证数据的安全性防止外部恶意修改数据同时也保护了数据的完整性和一 致性。接口访问封装通过接口访问类的内部数据和方法提供了一种良好的数据交互方式。外部世界只 能通过类的接口来访问内部数据和方法这种限制了外部世界对类的干扰使得类的实现更加稳定 和可靠。实现隔离封装使得类的实现细节被隐藏在类的内部外部世界无法访问类的实现细节。这样可以 使得类的实现更加自由可以在不影响外部世界的情况下自由修改和升级类的实现。可维护性封装提高了类的可维护性由于封装使得类的实现细节被隐藏起来类的内部实现可以 自由修改而不会影响外部世界对类的使用。这样可以使得类的维护更加方便和安全。重用性封装提高了类的重用性由于类的内部实现被隐藏起来外部世界只能通过类的接口来访 问内部数据和方法。这样可以使得类的接口更加通用和稳定从而提高了类的重用性。什么时候应用带参构造函数需要对对象进行一次性初始化时父类拥有带参构造函数子类继承父类也需要带参构造函数并调用父类构造函数。方法重载和重写的区别 重载OverLoading是多个重名函数具有不同的参数数据类型或参数个数。是一个类中多态性的 一种体现。但不能以返回类型作为重载函数的区分标准。两个同名函数具有相同的参数类型但是访问 权限不同或者返回类型不同是不可能的。 重写Overriding是子类继承父类重写父类的方法函数名参数和返回类型都要一样。子类所重 写方法的访问权限不能小于父类的。接口隔离原则和单一原则如何理解? 强调了代码的模块化、灵活性和可维护性 单一是指接口要尽量的智能单一不能为了实现一个接口而被迫实现不需要的方法情况。隔离的是实现 和调用这样才能真正解决团队的并行开发问题。 避免降低接口的灵活性和可用性。不适用异常处理程序会出现什么问题虚拟机会打印异常信息。程序终止运行 要把异常尽早处理这样产生的影响范围越小。因此不要把自己能处理的异常抛给调用者。finally在什么时候使用 finally是在任何情况下都会执行的部分。可以在查询数据库发生异常时关闭数据库连接。文件读取时关闭文件等等。不要在里边放return无论怎样都会返回这个值没有意义。throw和throws的区别 throw用来抛出异常在方法体内。 throws用来声明方法可能会抛出什么异常在函数声明之后。 简而言之throw关键字用于抛出一个异常对象throws关键字用于声明方法可能会抛出的异常类型。String和StringBuffer、StringBuilder的区别string和stringbuffer、stringbuiler都可一存储操作字符串String时不可以修改的后两者可以修改stringbuffer线程安全stringbuiler不安全String则是非线程安全的性能由于String是不可变的每次对String进行修改都会创建一个新的对象这会产生大量的垃 圾对象导致程序运行效率低下。而StringBuffer则是可变的不需要每次都创建新的对象因此 在处理大量字符串时使用StringBuffer的效率要比String高。多线程java中有几种方法可以实现线程 两种方法继承Thread类重写run()方法创建Thread对象调用start()方法启动线程。实现Runnable接口实现run()方法创建thread对象实现了runnable接口的对象传进去最后调 用start()方法。使用线程池避免频繁的创建和销毁线程用什么关键修饰同步方法 synchronized 关键字。 synchronized 修饰的方法称为同步方法它保证在任意时刻只有一个线程可 以执行该方法从而避免了多线程访问共享资源时出现的数据竞争和不一致性问题。 可以放在方法的生命出也可以放在方法的内部块中。 在方法声明处使用 synchronized 关键字时它会将整个方法体都变为同步代码块即只有一个线 程可以进入方法体内执行代码。 在方法内部块上使用 synchronized 关键字时它会将该代码块变为同步代码块即只有一个线程 可以执行该代码块内的代码。 // 继承Thread类创建线程 public class MyThread extends Thread { public void run() { System.out.println(“线程启动了”); } public static void main(String[] args) { MyThread myThread new MyThread(); myThread.start(); } } // 实现Runnable接口创建线程 public class MyRunnable implements Runnable { public void run() { System.out.println(“线程启动了”); } public static void main(String[] args) { MyRunnable myRunnable new MyRunnable(); Thread thread new Thread(myRunnable); thread.start(); } } public class MyCounter {为什么不推荐使用stop()和suspend()方法 stop() 方法会强制终止一个线程可能导致一些数据不一致或资源未释放的问题可能会破坏程 序的稳定性和完整性。因此推荐使用 interrupt() 方法来终止线程的执行因为 interrupt() 方法会给线程一个中断信号让线程自行判断是否终止执行并且可以在执行过程中清理资源和状 态。 suspend() 方法会暂停线程的执行但不会释放线程占用的锁这可能会导致死锁的发生。因 此推荐使用 wait() 和 notify() 方法来实现线程之间的协作和通信。sleep()和wait()的区别 sleep()是线程类Thread的static方法不释放锁。但会让出CPU执行时间分片。锁不释放不影响这 个过程如果其他线程都需要这个没有释放的锁那最终结果就是让出执行权大家都不执行。 wait()是Object类的方法释放锁暂停线程。直到其他线程调用了该对象的 notify() 或 notifyAll() 方法或者等待的时间到了。 wait() 方法主要用于多线程之间的协作和通信如 线程间的同步、通知和等待等。 sleep() 方法可以在任意时刻使用而 wait() 方法必须在 synchronized 块或方法中使用否则 会抛出 IllegalMonitorStateException 异常。 如果是控制线程的执行速度和时序可以使用 sleep() 方法如果是实现线程间的协作和通信 可以使用 wait() 方法。同时使用 wait() 方法时需要注意线程安全和死锁等问题。线程同步概念 private int count; // 同步方法 public synchronized void increment() { count; } public int getCount() { return count; } public static void main(String[] args) { MyCounter counter new MyCounter(); for (int i 0; i 1000; i) { new Thread(() - { counter.increment(); }).start(); } System.out.println(counter.getCount()); // 1000 } } package top.yanzx; import com.sun.org.apache.bcel.internal.generic.NEW; import java.lang.management.ThreadInfo; /**Author: yanzxDate: 2023/2/27 17:12Description: // Java 8之前 new Thread(new Runnable() {Overridepublic void run() {System.out.println(“Before Java8”);}}).start(); new Thread( () - System.out.println(“In Java8, Lambda expression”) ).start(); 创建任何类型的对象作为监视器 使用 synchronized()代码块或者方法 done */ public class Demo06ThreadSeller { public static int tickets 100; public static void main(String[] args) { // lambda相当于实现了runnable的run方法 Object obj new Object(); // 对象锁 Runnable seller () - { while (true){ // 加锁 synchronized(Demo06TheadCounter.class){ // 类锁类的字节码 // synchronized(obj){ // monitor enter 加锁 同步和异步的不同使用时间 多线程之间、共享数据需要存取修改等操作需要进行同步处理。 当程序执行了一个耗时较长的操作并且需要及时返回那么就需要使用异步先返回结果。在Monitor内部是如何做线程同步的 监视器和锁咋Java虚拟机中是一块使用的。监视器监视一块同步代码块确保每一次只有一个线程执行 同步代码块。每个监视器都和一个对象引用相关联。线程在获取锁之前不能执行临界区代码。锁和监视器二者区别 监视器是一种同步模型和java语言没有关系其他语言也可以使用监视器来进行同步代码块的访问 java语言是通过synchronized应该就是你说的锁关键字来声明同步块的具体是怎么同步的是使 用的监视器模型来同步的。 锁为实现监视器提供必要的支持。 Java中锁和监视器有以下区别1.基本概念不同2.主要作用不同3.执行机制不同。 基本概念不同在 于锁是对象内存堆中头部的一部分数据任何程序都可以使用它来协调对对象的多线程访问而监视 器是一种同步结构它允许线程同时互斥(使用锁)和协作。Java中什么是构造函数什么是的构造函数重载什 么是复制构造函数 构造函数创建对象时需要调用的函数。用于初始化对象的成员变量。默认会有无参构造函数。 构造函数重载根据参数列表不同具有多个构造函数。 // 临界区: 访问临界资源的那段代码 需要具有原子性 // 加锁被锁定的区域只有一个去执行synchronized关键字 try { if (tickets 0) break; Thread.sleep(10); // 不会释放锁所以会阻塞其他线程 System.out.println(Thread.currentThread().getName() “正在售卖第” tickets-- “张票”); } catch (InterruptedException e) { e.printStackTrace(); } }// monitor exit 释放锁 } }; new Thread(seller, “窗口1”).start(); new Thread(seller, “窗口2”).start(); new Thread(seller, “窗口3”).start(); new Thread(seller, “窗口4”).start(); } } 复制拷贝构造函数Java不支持C那样的复制构造函数这个不同点时因为java返回的是引 用类型。Java支持多继承吗 不支持一个类只能继承一个父类但是可以实现多个接口。谈谈你所理解的MVC Mmodel模型通常包含业务逻辑和数据访问逻辑负责数据的增删改查等操作 Vview视图层处理页面展示。 Ccontroller负责处理用户的交互事件。 降低了代码的耦合度。实现了代码的分层和模块化使得开发过程更加可控和可维护。通过MVC模式 可以将不同的职责分配到不同的模块中使得整个应用程序更加灵活和可扩展。例如可以在不改变模 型和视图的前提下只通过更改控制器来实现新的业务需求。 比如SpringMVC、Django、gingorm