当前位置: 首页 > news >正文

重庆本地建站校友会网站建设方案

重庆本地建站,校友会网站建设方案,一件代发货源网,做一个公司官网java平台的理解 谈谈你对 Java 平台的理解#xff1f;“Java 是解释执行”#xff0c;这句话正确么#xff1f; Java本身是一种面向对象的语音#xff0c;最显著的特性有两个方面#xff0c;一个是所谓的“书写一次#xff0c;到处运行”#xff08;Write once,run anyw…java平台的理解 谈谈你对 Java 平台的理解“Java 是解释执行”这句话正确么 Java本身是一种面向对象的语音最显著的特性有两个方面一个是所谓的“书写一次到处运行”Write once,run anywhere能够非常容易地获得跨平台能力另一个就是垃圾收集GCGarbage Collection Java源代码首先通过Javac编译成字节码bytecode然后在运行时通过Java虚拟机内嵌的解释器将字节码转换为最终的机器码。但是常见的JVM比如我们大多数情况下使用的Oracle JDK提供的Hotspot JVM,都提供了JIT(Just-In-Time)编译器也就是常说的动态编译器JIT能够在运行时将热点代码编译成机器码这种情况下部分热点代码就属于编译执行而不是解释执行了。Javac的编译编译Java源码生成“.class”文件里面实际是字节码而不是可以直接执行的机器码。Java通过字节码和JVM这种跨平台的抽象屏蔽了操作系统和硬件的细节这也是实现“一次编译到处运行”的基础。 Exception和Error有什么区别 throwable下分为error和exception 常见的error: OutofMemoryError,StackOveFlowError,NoClassDefFoundError, exceptionNullPointerException,runtimeException,classCastException等 实际开发中异常处理的两个原则 尽量不要捕获类似 Exception 这样的通用异常而是应该捕获特定异常 不要生吞swallow异常这是异常处理中要特别注意的事情因为很可能会导致非常难以诊断的诡异情况 生吞异常往往是基于假设这段代码可能不会发生或者感觉忽略异常是无所谓的但是千万不要在产品代码做这种假设 Throw early, catch late 原则 public void readPreferences(String filename) {Objects. requireNonNull(filename);//...perform other operations... InputStream in new FileInputStream(filename);//...read the preferences file... } 强引用、软引用、弱引用、幻象引用有什么区别具体使用场景是什么.. 强引用强引用是我们最常见的普通对象引用只要还有强引用指向一个对象就能表明对象还活着垃圾收集器不会碰这种对象。 软引用是一种相对强引用弱化一些的引用可以让对象豁免一些垃圾收集只有当JVM认为内存不足时才会去试图回收软引用指向的对象。软引用通常用来实现内存敏感的缓存如果还有空闲内存就可以暂时保留缓存当内存不足时清理掉这样就保证了使用缓存的同时不会耗尽内存。软引用可以和一个引用队列ReferenceQueue联合使用如果软引用所引用的对象被垃圾回收器回收Java虚拟机就会把这个软引用加入到与之关联的引用队列中。后续我们可以调用ReferenceQueue的poll()方法来检查是否有它所关心的对象被回收。如果队列为空将返回一个null,否则该方法返回队列中前面的一个Reference对象 弱引用并不能使对象豁免垃圾收集仅仅是提供一种访问在弱引用状态下对象的途径。这就可以用来构建一种没有特定约束的关系比如维护一种非强制性的映射关系如果试图获取时对象还在就使用它否则重新实例化。它同样是很多缓存实现的选择 虚引用幻象引用也叫虚引用不能通过它来访问对象用幻象引用监控对象的创建和销毁 对象可达性状态流转分析 String、StringBuffer、StringBuilder有什么区别 String 是 Java 语言非常基础和重要的类提供了构造和管理字符串的各种基本逻辑。它是典型的 Immutable 类被声明成为 final class所有属性也都是 final 的。也由于它的不可变性类似拼接、裁剪字符串等动作都会产生新的 String 对象。由于字符串操作的普遍性所以相关操作的效率往往对应用性能有明显影响 StringBuffer 本质是一个线程安全的可修改字符序列它保证了线程安全也随之带来了额外的性能开销。如果没有线程安全的需要推荐使用它的后继者也就是 StringBuilder。 字符串的设计和实现考量StringBuffer 和 StringBuilder 底层都是利用可修改的charJDK 9 以后是 byte数组二者都继承了 AbstractStringBuilder里面包含了基本操作区别仅在于最终的方法是否加了 synchronized。目前的实现是构建时初始字符串长度加 16如果没有构建对象时输入最初的字符串那么初始值就是 16。 String的演化Java 的字符串在历史版本中使用 char 数组来存数据的Java 中的 char 是两个 bytes 大小拉丁语系语言的字符根本就不需要太宽的 char这样无区别的实现就造成了一定的浪费。密度是编程语言平台永恒的话题因为归根结底绝大部分任务是要来操作数据的。Java 9 中我们引入了 Compact Strings 的设计对字符串进行了大刀阔斧的改进。将数据存储方式从 char 数组改变为一个 byte 数组加上一个标识编码的所谓 coder并且将相关字符串操作类都进行了修改。另外所有相关的 Intrinsic 之类也都进行了重写以保证没有任何性能损失。紧凑字符串带来的优势即更小的内存占用、更快的操作速度。 很多字符串操作比如 getBytes()/String(byte[] bytes) 等都是隐含着使用平台默认编码这是一种好的实践吗是否有利于避免乱码 getBytes和String相关的转换时根据业务需要建议指定编码方式如果不指定则看看JVM参数里有没有指定file.encoding参数如果JVM没有指定那使用的默认编码就是运行的操作系统环境的编码了那这个编码就变得不确定了。常见的编码iso8859-1是单字节编码UTF-8是变长的编码。 动态代理是基于什么原理 反射它就像是一种魔法引入运行时自省能力赋予了 Java 语言令人意外的活力通过运行时操作元数据或对象Java 可以灵活地操作运行时才能确定的信息。而动态代理则是延伸出来的一种广泛应用于产品开发中的技术很多繁琐的重复编程都可以被动态代理机制优雅地解决 动态代理应用非常广泛虽然最初多是因为 RPC 等使用进入我们视线但是动态代理的使用场景远远不仅如此它完美符合 Spring AOP 等切面编程。我在后面的专栏还会进一步详细分析 AOP 的目的和能力。简单来说它可以看作是对 OOP 的一个补充因为 OOP 对于跨越不同对象或类的分散、纠缠逻辑表现力不够比如在不同模块的特定阶段做一些事情类似日志、用户鉴权、全局性异常处理、性能监控甚至事务处理等你可以参考下面这张图 AOP 通过动态代理机制可以让开发者从这些繁琐事项中抽身出来大幅度提高了代码的抽象程度和复用度。从逻辑上来说我们在软件设计和实现中的类似代理如 Facade、Observer 等很多设计目的都可以通过动态代理优雅地实现。 int和Integer有什么区别 自动装箱 / 自动拆箱是发生在什么阶段 自动装箱实际上算是一种语法糖.Java 平台为我们自动进行了一些转换保证不同的写法在运行时等价它们发生在编译阶段也就是生成的字节码是一致的 自动装箱 / 自动拆箱似乎很酷在编程实践中有什么需要注意的吗 原则上建议避免无意中的装箱、拆箱行为尤其是在性能敏感的场合创建 10 万个 Java 对象和 10 万个整数的开销可不是一个数量级的不管是内存使用还是处理速度光是对象头的空间占用就已经是数量级的差距了 扩展使用原始数据类型、数组甚至本地代码实现等在性能极度敏感的场景往往具有比较大的优势用其替换掉包装类、动态数组如 ArrayList等可以作为性能优化的备选项。一些追求极致性能的产品或者类库会极力避免创建过多对象。当然在大多数产品代码里并没有必要这么做还是以开发效率优先 对比Vector、ArrayList、LinkedList有何区别 Vector 是 Java 早期提供的线程安全的动态数组如果不需要线程安全并不建议选择毕竟同步是有额外开销的。Vector 内部是使用对象数组来保存数据可以根据需要自动的增加容量当数组已满时会创建新的数组并拷贝原有数组数据 ArrayList 是应用更加广泛的动态数组实现它本身不是线程安全的所以性能要好很多。与 Vector 近似ArrayList 也是可以根据需要调整容量不过两者的调整逻辑有所区别Vector 在扩容时会提高 1 倍而 ArrayList 则是增加 50% LinkedList 顾名思义是 Java 提供的双向链表所以它不需要像上面两种那样调整容量它也不是线程安全的 也可以补充一下不同容器类型适合的场景 Vector 和 ArrayList 作为动态数组其内部元素以数组形式顺序存储的所以非常适合随机访问的场合。除了尾部插入和删除元素往往性能会相对较差比如我们在中间位置插入一个元素需要移动后续所有元素。 而 LinkedList 进行节点插入、删除却要高效得多但是随机访问性能则要比动态数组慢 在应用开发中如果事先可以估计到应用操作是偏向于插入、删除还是随机访问较多就可以针对性的进行选择 在 Java 8 之中Java 平台支持了 Lambda 和 Stream相应的 Java 集合框架也进行了大范围的增强以支持类似为集合创建相应 stream 或者 parallelStream 的方法实现我们可以非常方便的实现函数式代码。在 Java 9 中Java 标准类库提供了一系列的静态工厂方法比如List.of()、Set.of()大大简化了构建小的容器实例的代码量 ​ ArrayListString  list new ArrayList();list.add(Hello);list.add(World); //利用新的容器静态工厂方法 ListString simpleList List.of(Hello,world); 对比Hashtable、HashMap、TreeMap有什么不同 Hashtable 是早期 Java 类库提供的一个哈希表实现本身是同步的不支持 null 键和值由于同步导致的性能开销所以已经很少被推荐使用。 HashMap 是应用更加广泛的哈希表实现行为上大致上与 HashTable 一致主要区别在于 HashMap 不是同步的支持 null 键和值等。通常情况下HashMap 进行 put 或者 get 操作可以达到常数时间的性能所以它是绝大部分利用键值对存取场景的首选 TreeMap 则是基于红黑树的一种提供顺序访问的 Map和 HashMap 不同它的 get、put、remove 之类操作都是 Olog(n)的时间复杂度具体顺序可以由指定的 Comparator 来决定或者根据键的自然顺序来判断。 hashmap扩容时为什么这里需要将高位数据移位到低位进行异或运算呢 这是因为有些数据计算出的哈希值差异主要在高位而 HashMap 里的哈希寻址是忽略容量以上的高位的那么这种处理就可以有效避免类似情况下的哈希碰撞 为什么 HashMap 要树化呢 本质上这是个安全问题。因为在元素放置过程中如果一个对象哈希冲突都被放置到同一个桶里则会形成一个链表我们知道链表查询是线性的会严重影响存取的性能。 而在现实世界构造哈希冲突的数据并不是非常复杂的事情恶意代码就可以利用这些数据大量与服务器端交互导致服务器端 CPU 大量占用这就构成了哈希碰撞拒绝服务攻击国内一线互联网公司就发生过类似攻击事件 解决哈希冲突的常用方法有: 开放定址当关键字key的哈希地址pHkey出现冲突时以p为基础产生另一个哈希地址p1如果p1仍然冲突再以p为基础产生另一个哈希地址p2…直到找出一个不冲突的哈希地址pi 将相应元素存入其中。 再哈希法这种方法是同时构造多个不同的哈希函数 HiRH1key i12…k当哈希地址HiRH1key发生冲突时再计算HiRH2key……直到冲突不再产生。这种方法不易产生聚集但增加了计算时间。 链地址这种方法的基本思想是将所有哈希地址为i的元素构成一个称为同义词链的单链表并将单链表的头指针存在哈希表的第i个单元中因而查找、插入和删除主要在同义词链中进行。链地址法适用于经常进行插入和删除的情况。 ConcurrentHashMap如何实现高效地线程安全 Java 提供了不同层面的线程安全支持。在传统集合框架内部除了 Hashtable 等同步容器还提供了所谓的同步包装器Synchronized Wrapper我们可以调用 Collections 工具类提供的包装方法来获取一个同步的包装容器如 Collections.synchronizedMap但是它们都是利用非常粗粒度的同步方式在高并发情况下性能比较低下。 另外更加普遍的选择是利用并发包提供的线程安全容器类它提供了 各种并发容器比如 ConcurrentHashMap、CopyOnWriteArrayList。 各种线程安全队列Queue/Deque如 ArrayBlockingQueue、SynchronousQueue。 各种有序容器的线程安全版本等。 具体保证线程安全的方式包括有从简单的 synchronize 方式到基于更加精细化的比如基于分离锁实现的 ConcurrentHashMap 等并发实现等。具体选择要看开发的场景需求总体来说并发包内提供的容器通用场景远优于早期的简单同步实现。 为什么需要 ConcurrentHashMap Hashtable 本身比较低效因为它的实现基本就是将 put、get、size 等各种方法加上“synchronized”。简单来说这就导致了所有并发操作都要竞争同一把锁一个线程在进行同步操作时其他线程只能等待大大降低了并发操作的效率 Collections 提供的同步包装器只是利用输入 Map 构造了另一个同步版本所有操作虽然不再声明成为 synchronized 方法但是还是利用了“this”作为互斥的 mutex没有真正意义上的改进 构造的时候Segment 的数量由所谓的 concurrentcyLevel 决定默认是 16 在JDK1.7中ConcurrentHashMap采用Segment HashEntry的方式进行实现结构如下 一个 ConcurrentHashMap 里包含一个 Segment 数组。Segment 的结构和HashMap类似是一种数组和链表结构一个 Segment 包含一个 HashEntry 数组每个 HashEntry 是一个链表结构的元素每个 Segment 守护着一个HashEntry数组里的元素当对 HashEntry 数组的数据进行修改时必须首先获得对应的 Segment的锁。 ———————————————— 版权声明本文为CSDN博主「Java程序员-张凯」的原创文章遵循CC 4.0 BY-SA版权协议转载请附上原文出处链接及本声明。 原文链接https://blog.csdn.net/qq_41701956/article/details/110119625 在JDK1.8中放弃了Segment臃肿的设计取而代之的是采用Node CAS Synchronized来保证并发安全进行实现synchronized只锁定当前链表或红黑二叉树的首节点这样只要hash不冲突就不会产生并发效率又提升N倍。 Java提供了哪些IO方式 NIO如何实现多路复用 javaio分为同步阻塞IO在读取输入流或者写入输出流时在读、写动作完成之前线程会一直阻塞在那里它们之间的调用是可靠的线性顺序。 优点代码比较简单、直观 缺点则是 IO 效率和扩展性存在局限性容易成为应用性能的瓶颈。 java1.4引入了NIO框架提供了Channel、Selector、Buffer等抽象构建多路复用的、同步非阻塞 IO 程序同时提供了更接近操作系统底层的高性能数据操作方式。 java7中引入了AIO异步非阻塞 IO 方式。基于事件和回调机制。应用操作直接返回而不会阻塞在那里当后台处理完成操作系统会通知相应线程进行后续工作。 BIO、NIO、NIO 2AIO 基础 API 功能与设计 InputStream/OutputStream 和 Reader/Writer 的关系和区别。 NIO、NI O 2 的基本组成。 给定场景分别用不同模型实现分析 BIO、NIO 等模式的设计和实现原理。 NIO 提供的高性能数据操作方式是基于什么原理如何使用 或者从开发者的角度来看你觉得 NIO 自身实现存在哪些问题有什么改进的想法吗 概念区分同步或异步synchronous/asynchronous。简单来说同步是一种可靠的有序运行机制当我们进行同步操作时后续的任务是等待当前调用返回才会进行下一步而异步则相反其他任务不需要等待当前调用返回通常依靠事件、回调等机制来实现任务间次序关系。 区分阻塞与非阻塞blocking/non-blocking。在进行阻塞操作时当前线程会处于阻塞状态无法从事其他任务只有当条件就绪才能继续比如 ServerSocket 新连接建立完毕或数据读取、写入操作完成而非阻塞则是不管 IO 操作是否结束直接返回相应操作在后台继续处理。 IO 不仅仅是对文件的操作网络编程中比如 Socket 通信都是典型的 IO 操作目标。 输入流、输出流InputStream/OutputStream是用于读取或写入字节的例如操作图片文件。 而 Reader/Writer 则是用于操作字符增加了字符编解码等功能适用于类似从文件中读取或者写入文本信息。本质上计算机操作的都是字节不管是网络通信还是文件读取Reader/Writer 相当于构建了应用逻辑和原始数据之间的桥梁。 BufferedOutputStream 等带缓冲区的实现可以避免频繁的磁盘读写进而提高 IO 处理效率。这种设计利用了缓冲区将批量数据进行一次操作但在使用中千万别忘了 flush。 Java NIO 概览 首先熟悉一下 NIO 的主要组成部分 Buffer高效的数据容器除了布尔类型所有原始数据类型都有相应的 Buffer 实现。 Channel类似在 Linux 之类操作系统上看到的文件描述符是 NIO 中被用来支持批量式 IO 操作的一种抽象。 File 或者 Socket通常被认为是比较高层次的抽象而 Channel 则是更加操作系统底层的一种抽象这也使得 NIO 得以充分利用现代操作系统底层机制获得特定场景的性能优化例如DMADirect Memory Access等。不同层次的抽象是相互关联的我们可以通过 Socket 获取 Channel反之亦然。 Selector是 NIO 实现多路复用的基础它提供了一种高效的机制可以检测到注册在 Selector 上的多个 Channel 中是否有 Channel 处于就绪状态进而实现了单线程对多 Channel 的高效管理。 Chartset提供 Unicode 字符串定义NIO 也提供了相应的编解码器等例如通过下面的方式进行字符串到 ByteBuffer 的转换 NIO能解决什么问题 场景 ​ public class DemoServer extends Thread {private ServerSocket serverSocket;public int getPort() {return  serverSocket.getLocalPort();}public void run() {try {serverSocket new ServerSocket(0);while (true) {Socket socket serverSocket.accept();RequestHandler requestHandler new RequestHandler(socket);requestHandler.start();}} catch (IOException e) {e.printStackTrace();} finally {if (serverSocket ! null) {try {serverSocket.close();} catch (IOException e) {e.printStackTrace();};}}}public static void main(String[] args) throws IOException {DemoServer server new DemoServer();server.start();try (Socket client new Socket(InetAddress.getLocalHost(), server.getPort())) {BufferedReader bufferedReader new BufferedReader(new                   InputStreamReader(client.getInputStream()));bufferedReader.lines().forEach(s - System.out.println(s));}}} // 简化实现不做读取直接发送字符串 class RequestHandler extends Thread {private Socket socket;RequestHandler(Socket socket) {this.socket socket;}Overridepublic void run() {try (PrintWriter out new PrintWriter(socket.getOutputStream());) {out.println(Hello world!);out.flush();} catch (Exception e) {e.printStackTrace();}}} ​ 稍微修正一下这个问题我们引入线程池机制来避免浪费 ​ serverSocket new ServerSocket(0); executor Executors.newFixedThreadPool(8);while (true) {Socket socket serverSocket.accept();RequestHandler requestHandler new RequestHandler(socket);executor.execute(requestHandler); } 如果连接数并不是非常多只有最多几百个连接的普通应用这种模式往往可以工作的很好。但是如果连接数量急剧上升这种实现方式就无法很好地工作了因为线程上下文切换开销会在高并发时变得很明显这是同步阻塞方式的低扩展性劣势. NIO 则是利用了单线程轮询事件的机制通过高效地定位就绪的 Channel来决定做什么仅仅 select 阶段是阻塞的可以有效避免大量客户端连接时频繁线程切换带来的问题应用的扩展能力有了非常大的提高 NIO 引入的多路复用机制提供了另外一种思路 public class NIOServer extends Thread {public void run() {try (Selector selector Selector.open();ServerSocketChannel serverSocket ServerSocketChannel.open();) {// 创建 Selector 和 ChannelserverSocket.bind(new InetSocketAddress(InetAddress.getLocalHost(), 8888));serverSocket.configureBlocking(false);// 注册到 Selector并说明关注点serverSocket.register(selector, SelectionKey.OP_ACCEPT);while (true) {selector.select();// 阻塞等待就绪的 Channel这是关键点之一SetSelectionKey selectedKeys selector.selectedKeys();IteratorSelectionKey iter selectedKeys.iterator();while (iter.hasNext()) {SelectionKey key iter.next();// 生产系统中一般会额外进行就绪状态检查sayHelloWorld((ServerSocketChannel) key.channel());iter.remove();}}} catch (IOException e) {e.printStackTrace();}}private void sayHelloWorld(ServerSocketChannel server) throws IOException {try (SocketChannel client server.accept();) {          client.write(Charset.defaultCharset().encode(Hello world!));}}// 省略了与前面类似的 main } 在 Java 7 引入的 NIO 2 中又增添了一种额外的异步 IO 模式利用事件和回调处理 Accept、Read 等操作。 AIO 实现看起来是类似这样子 AsynchronousServerSocketChannel serverSock        AsynchronousServerSocketChannel.open().bind(sockAddr); serverSock.accept(serverSock, new CompletionHandler() { // 为异步操作指定 CompletionHandler 回调函数Overridepublic void completed(AsynchronousSocketChannel sockChannel, AsynchronousServerSocketChannel serverSock) {serverSock.accept(serverSock, this);// 另外一个 writesockCompletionHandler{}sayHelloWorld(sockChannel, Charset.defaultCharset().encode(Hello World!));}// 省略其他路径处理方法... }); 谈谈接口和抽象类有什么区别 接口接口是对行为的抽象是抽象方法的集合。利用接口可以达到API定义和实现分离的目的。接口不能实例化不能包含任何非常量成员任何 field 都是隐含着 public static final 的意义同时没有非静态方法实现也就是说要么是抽象方法要么是静态方法。实现接口用 implements关键字 抽象类抽象类是不能实例化的类用 abstract 关键字修饰 class其目的主要是代码重用。其他和一般的java类没有太大区别可有一个或者多个抽象方法也可以没有。用extends关键字继承。 Java 不支持多继承。java可以实现了多个接口因为接口是抽象方法的集合。在一些情况下存在特定场景需要抽象出与具体实现、实例化无关的通用逻辑或者纯调用关系的逻辑但是使用传统的抽象类会陷入到单继承的窘境。以往常见的做法是实现由静态方法组成的工具类Utils比如 java.util.Collections。 为接口添加任何抽象方法相应的所有实现了这个接口的类也必须实现新增方法否则会出现编译错误。对于抽象类如果我们添加非抽象方法其子类只会享受到能力扩展而不用担心编译出问题 有一类没有任何方法的接口通常叫作 Marker Interface顾名思义它的目的就是为了声明某些东西。这类似于注明annotation对于 Annotation因为可以指定参数和值在表达能力上要更强大一些所以更多人选择使用 Annotation。 Java 8 增加了函数式编程的支持所以又增加了一类定义即所谓 functional interface简单说就是只有一个抽象方法的接口通常建议使用 FunctionalInterface Annotation 来标记。 Java 8 开始interface 增加了对 default method 的支持。Java 9 以后甚至可以定义 private default method. public interface CollectionE extends IterableE {/*** Returns a sequential Stream with this collection as its source* ...**/default StreamE stream() {return StreamSupport.stream(spliterator(), false);}} 进行面向对象编程掌握基本的设计原则是必须的我今天介绍最通用的部分也就是所谓的 S.O.L.I.D 原则。 单一职责Single Responsibility类或者对象最好是只有单一职责在程序设计中如果发现某个类承担着多种义务可以考虑进行拆分。 开关原则Open-Close, Open for extension, close for modification设计要对扩展开放对修改关闭。换句话说程序设计应保证平滑的扩展性尽量避免因为新增同类功能而修改已有实现这样可以少产出些回归regression问题。 里氏替换Liskov Substitution这是面向对象的基本要素之一进行继承关系抽象时凡是可以用父类或者基类的地方都可以用子类替换。 接口分离Interface Segregation我们在进行类和接口设计时如果在一个接口里定义了太多方法其子类很可能面临两难就是只有部分方法对它是有意义的这就破坏了程序的内聚性。 对于这种情况可以通过拆分成功能单一的多个接口将行为进行解耦。在未来维护中如果某个接口设计有变不会对使用其他接口的子类构成影响。 依赖反转Dependency Inversion实体应该依赖于抽象而不是实现。也就是说高层次模块不应该依赖于低层次模块而是应该基于抽象。实践这一原则是保证产品代码之间适当耦合度的法宝。 synchronized和ReentrantLock有什么区别呢 锁作为并发的基础工具之一你至少需要掌握 理解什么是线程安全。 synchronized、ReentrantLock 等机制的基本使用与案例。 更近一步你还需要 掌握 synchronized、ReentrantLock 底层实现理解锁膨胀、降级理解偏斜锁、自旋锁、轻量级锁、重量级锁等概念。 掌握并发包中 java.util.concurrent.lock 各种不同实现和案例分析。 线程安全保证多线程环境下共享的、可修改的状态数据的正确性 线程安全需要保证几个基本特性 原子性简单说就是相关操作不会中途被其他线程干扰一般通过同步机制实现。 可见性是一个线程修改了某个共享变量其状态能够立即被其他线程知晓通常被解释为将线程本地状态反映到主内存上volatile 就是负责保证可见性的。 有序性是保证线程内串行语义避免指令重排等 在JDk的API里对于join()方法是 join public final void join() throws InterruptedException Waits for this thread to die. Throws: InterruptedException - if any thread has interrupted the current thread. The interrupted status of the current thread is cleared when this exception is thrown. 即join()的作用是“等待该线程终止”这里需要理解的就是该线程是指的主线程等待子线程的终止。也就是在子线程调用了join()方法后面的代码只有等到子线程结束了才能执行。也就是让外部线程等待该线程结束后再继续执行如果不调用join方法则主线程不会等待子线程执行完各执行各的。 public class ThreadSafeSample {public int sharedState;public void nonSafeAction() {while (sharedState 100000) {int former sharedState;int latter sharedState;if (former ! latter - 1) {System.out.printf(Observed data race, former is former , latter is latter);}}}public static void main(String[] args) throws InterruptedException {ThreadSafeSample sample new ThreadSafeSample();Thread threadA new Thread(){public void run(){sample.nonSafeAction();}};Thread threadB new Thread(){public void run(){sample.nonSafeAction();}};threadA.start();threadB.start();threadA.join();threadB.join();} } synchronized底层如何实现什么是锁的升级、降级 synchronized 代码块是由一对儿 monitorenter/monitorexit 指令实现的Monitor 对象是同步的基本实现单元。 在 Java 6 之前Monitor 的实现完全是依靠操作系统内部的互斥锁因为需要进行用户态到内核态的切换所以同步操作是一个无差别的重量级操作。 现代的OracleJDK 中JVM 对此进行了大刀阔斧地改进提供了三种不同的 Monitor 实现也就是常说的三种不同的锁偏斜锁Biased Locking、轻量级锁和重量级锁大大改进了其性能 所谓锁的升级、降级就是 JVM 优化 synchronized 运行的机制当 JVM 检测到不同的竞争状况时会自动切换到适合的锁实现这种切换就是锁的升级、降级。 synchronized 是 JVM 内部的 Intrinsic Lock所以偏斜锁、轻量级锁、重量级锁的代码实现并不在核心类库部分而是在 JVM 的代码中。 线程自身的方法除了 start还有个 join 方法等待线程结束yield 是告诉调度器主动让出 CPU另外就是一些已经被标记为过时的 resume、stop、suspend 之类据我所知在 JDK 最新版本中destory/stop 方法将被直接移除。 Spring事务不起作用 问题汇总 spring事务transactional注解不起作用
http://www.zqtcl.cn/news/590764/

相关文章:

  • 上海网站建设免the 7 wordpress
  • 知名建站的公司微信企业app手机下载安装
  • 鹤山做网站羊毛网站建设视频
  • 图书类网站开发的背景建筑培训机构
  • 外贸网站建设制作wordpress管理员页面404
  • 北郊网站建设app网站开发哪里有
  • 像素人物制作网站网站开发的话术
  • 网站关键词怎么优化排名wordpress电子商城模板
  • 电子商务网站建设与维护能赚多少钱成交型网站建设
  • 到国外做网站网站是怎么回事中国一级建造师网官网
  • 惠州网站建设哪家好网站对图片优化
  • 酒店网站建设报价详情wordpress表单留言
  • 58同城做公司网站怎修改在线葡京在线葡京
  • 家纺网站模板wordpress折叠菜单
  • 建设信用中国网站站群系统破解版
  • 百度怎么投放广告凡科网站可以做seo优化
  • 医院网站建设 不足好的手机网站建设公司
  • 简历上作品展示网站链接怎么做wordpress的登陆地址修改密码
  • 深圳做响应式网站公司公司网站开发费用放在什么科目
  • 网站页面上的悬浮窗怎么做简单好看的版面设计图
  • 我要在58上面做网站硬件开发和嵌入式的区别
  • 西安网站推广慧创新手怎么开网店
  • 做羞羞事视频网站网站策划书基本项目
  • 对网站建设的维护优秀设计网站推荐
  • 口红机网站怎么做wordpress 搭建个人网站
  • 黄金网站房地产网站建设意义
  • 百度网站联盟公司做网站计入那个科目
  • 越秀电子商务网站建设国外的ui设计思想网站
  • 网站关键词优化公司网站建设完成确认书
  • 企业微信网站怎么建设山东有哪些网络公司