幸运快艇真人百家乐网站会员权益_口试中时时被问到Java援用类型旨趣,带你深切判辨
发布日期:2023-10-30 04:24    点击次数:95

幸运快艇真人百家乐网站会员权益_口试中时时被问到Java援用类型旨趣,带你深切判辨

幸运快艇真人百家乐网站会员权益_ 1.选拔唯独性索引

唯独性索引的值是唯独的,不错更快速的通过该索引来细目某笔纪录。举例,学生表中学号是具有唯独性的字段。为该字段耕作唯独性索引不错很快的细目某个学生的信息。如果使用姓名的话,可能存在同名时事,从而缩短查询速率。

2.为时时需要排序、分组和蚁合操作的字段耕作索引

时时需要ORDER BY、GROUP BY、DISTINCT和UNION等操作的字段,排序操作会蹧跶好多本领。如果为其耕作索引,不错有用地幸免排序操作。

3.为常手脚查询条款的字段耕作索引

如果某个字段时时用来作念查询条款,那么该字段的查询速率会影响通盘这个词表的查询速率。因此,为这么的字段耕作索引,不错进步通盘这个词表的查询速率。

4.摈弃索引的数量

索引的数量不是越多越好。每个索引都需要占用磁盘空间,索引越多,需要的磁盘空间就越大。修改表时,对索引的重构和更新很难题。越多的索引,会使更新表变得很蹧跶本领。

5.尽量使用数据量少的索引

如果索引的值很长,那么查询的速率会受到影响。举例,对一个CHAR(100)类型的字段进行全文检索需要的本领深信要比对CHAR(10)类型的字段需要的本领要多。

6.尽量使用前缀来索引

如果索引字段的值很长,最佳使用值的前缀来索引。举例,TEXT和BLOG类型的字段,进行全文检索会很蹧跶本领。如果只检索字段的前边的多少个字符,这么不错进步检索速率。

7.删除不再使用或者很少使用的索引

表中的数据被无数更新,或者数据的使用花式被改变后,原有的一些索引可能不再需要。数据库处置员应当依期找出这些索引,将它们删除,从而减少索引对更新操作的影响。

8.最左前缀匹配原则,终点蹙迫的原则。

mysql会一直向右匹配直到遭受界限查询(>、<、between、like)就住手匹配,比如a 1=”” and=”” b=”2” c=”“> 3 and d = 4 如果耕作(a,b,c,d)法例的索引,d是用不到索引的,如果耕作(a,b,d,c)的索引则都不错用到,a,b,d的法例不错大肆养息。

网站会员权益XXX已经成为一名顶尖体育明星,表现惊叹不已。曾,成功得益于一直以来努力坚持。 9.=和in不错乱序。

比如a = 1 and b = 2 and c = 3 耕作(a,b,c)索引不错大肆法例,mysql的查询优化器会帮你优化成索引不错识别的神情

10.尽量选拔分手度高的列手脚索引。

分手度的公式是count(distinct col)/count(*),默示字段不重迭的比例,比例越大咱们扫描的纪录数越少,唯独键的分手度是1,而一些现象、性别字段可能在大数据面前分手度就 是0,那可能有东说念主会问,这个比例有什么教会值吗?使用场景不同,这个值也很难细目,一般需要join的字段咱们都要求是0.1以上,即平均1条扫描10条 纪录

11.索引列不可参与斟酌,保握列“干净”。

比如from_unixtime(create_time) = ’2014-05-29’就不可使用到索引,原因很简便,b+树中存的都是数据表中的字段值,但进行检索时,需要把通盘元素都愚弄函数才气相比,光显资本 太大。是以语句应该写成create_time = unix_timestamp(’2014-05-29’);

12.尽量的推广索引,不要新建索引。

比如表中还是有a的索引,咫尺要加(a,b)的索引,那么只需要修改正本的索引即可

闪耀:选拔索引的最终见识是为了使查询的速率变快。上头给出的原则是最基本的准则,但不可死板于上头的准则。读者要在以后的学习和使命中进行不断的履行。字据愚弄的骨子情况进行分析和判断,选拔最合适的索引花式。

Java中一共有4种援用类型(其实还有一些其他的援用类型比如FinalReference):强援用、软援用、弱援用、虚援用。

澳门新葡京网址

其中强援用等于咱们时时使用的Object a = new Object(); 这么的神情,在Java中并莫得对应的Reference类。

兑换皇冠app

本篇著作东若是分析软援用、弱援用、虚援用的兑现,这三种援用类型都是收受于Reference这个类,主要逻辑也在Reference中。

问题

在分析前,先抛几个问题?

网上大多数著作关于软援用的先容是:在内存不及的时候才会被回收,那内存不及是若何界说的?什么才叫内存不及? 网上大多数著作关于虚援用的先容是:形同虚设,虚援用并不会决定对象的生命周期。主要用来追踪对象被垃圾回收器回收的行径。竟然是这么吗? 虚援用在Jdk中有哪些场景下用到了呢? Reference

咱们先看下Reference.java中的几个字段

public 亚新轮盘abstract class Reference<T> {     //援用的对象     private T referent;             //回收队伍,由使用者在Reference的构造函数中指定     volatile ReferenceQueue<? super T> queue;      //当该援用被加入到queue中的时候,该字段被诞生为queue中的下一个元素,以形成链表结构     volatile Reference next;     //在GC时,JVM底层会惊叹一个叫DiscoveredList的链表,存放的是Reference对象,discovered字段指向的等于链表中的下一个元素,由JVM诞生     transient private Reference<T> discovered;       //进行线程同步的锁对象     static private class Lock { }     private static Lock lock = new Lock();     //恭候加入queue的Reference对象,在GC时由JVM诞生,会有一个java层的线程(ReferenceHandler)源源链接的从pending中索要元素加入到queue     private static Reference<Object> pending = null; } 

一个Reference对象的生命周期如下:

主要分为Native层和Java层两个部分。

Native层在GC时将需要被回收的Reference对象加入到DiscoveredList中(代码在referenceProcessor.cpp中

process_discovered_references步调),然后将DiscoveredList的元素移动到PendingList中(代码在referenceProcessor.cpp中enqueue_discovered_ref_helper步调),PendingList的队首等于Reference类中的pending对象。

望望Java层的代码

private static class ReferenceHandler extends Thread {          ...         public void run() {             while (true) {                 tryHandlePending(true);             }         }   }  static boolean tryHandlePending(boolean waitForNotify) {         Reference<Object> r;         Cleaner c;         try {             synchronized (lock) {                 if (pending != null) {                     r = pending;                      //如果是Cleaner对象,则纪录下来,底下作念特殊处理                     c = r instanceof Cleaner ? (Cleaner) r : null;                     //指向PendingList的下一个对象                     pending = r.discovered;                     r.discovered = null;                 } else {                    //如果pending为null就先恭候,当有对象加入到PendingList中时,jvm会履行notify                     if (waitForNotify) {                         lock.wait();                     }                     // retry if waited                     return waitForNotify;                 }             }         }          ...          // 如果时CLeaner对象,则调用clean步调进行资源回收         if (c != null) {             c.clean();             return true;         }         //将Reference加入到ReferenceQueue,设备者不错通过从ReferenceQueue中poll元素感知到对象被回收的事件。         ReferenceQueue<? super Object> q = r.queue;         if (q != ReferenceQueue.NULL) q.enqueue(r);         return true;  } 

过程相比简便:等于源源链接的从PendingList中索要出元素,然后将其加入到ReferenceQueue中去,设备者不错通过从ReferenceQueue中poll元素感知到对象被回收的事件。

另外需要闪耀的是,关于Cleaner类型(收受自虚援用)的对象会有格外的处理:在其指向的对象被回收时,会调用clean步调,该步调主若是用来作念对应的资源回收,在堆外内存DirectByteBuffer中等于用Cleaner进行堆外内存的回收,这亦然虚援用在java中的典型愚弄。

看罢了Reference的兑现,再望望几个兑现类里,各自有什么不同。

SoftReference

public class SoftReference<T> extends Reference<T> {      static private long clock;      private long timestamp;      public SoftReference(T referent) {         super(referent);         this.timestamp = clock;     }      public SoftReference(T referent, ReferenceQueue<? super T> q) {         super(referent, q);         this.timestamp = clock;     }      public T get() {         T o = super.get();         if (o != null && this.timestamp != clock)             this.timestamp = clock;         return o;     }  } 

软援用的兑现很简便,就多了两个字段:clock和timestamp。clock是个静态变量,每次GC时都会将该字段诞生成面前本领。timestamp字段则会在每次调用get步调时将其赋值为clock(如果不相配且对象没被回收)。

那这两个字段的作用是什么呢?这和软援用在内存不够的时候才被回收,又有什么关系呢?

这些还得看JVM的源码才行,因为决定对象是否需要被回收都是在GC中兑现的。

size_t ReferenceProcessor::process_discovered_reflist(   DiscoveredList               refs_lists[],   ReferencePolicy*             policy,   bool                         clear_referent,   BoolObjectClosure*           is_alive,   OopClosure*                  keep_alive,   VoidClosure*                 complete_gc,   AbstractRefProcTaskExecutor* task_executor) {  ...    //还记起上文提到过的DiscoveredList吗?refs_lists等于DiscoveredList。    //关于DiscoveredList的处理分为几个阶段,SoftReference的处理就在第一阶段  ...       for (uint i = 0; i < _max_num_q; i++) {         process_phase1(refs_lists[i], policy,                        is_alive, keep_alive, complete_gc);       }  ... }  //该阶段的主要见识等于当内存填塞时,将对应的SoftReference从refs_list中移除。 void ReferenceProcessor::process_phase1(DiscoveredList&    refs_list,                                    ReferencePolicy*   policy,                                    BoolObjectClosure* is_alive,                                    OopClosure*        keep_alive,                                    VoidClosure*       complete_gc) {    DiscoveredListIterator iter(refs_list, keep_alive, is_alive);   // Decide which softly reachable refs should be kept alive.   while (iter.has_next()) {     iter.load_ptrs(DEBUG_ONLY(!discovery_is_atomic() /* allow_null_referent */));     //判断援用的对象是否存活     bool referent_is_dead = (iter.referent() != NULL) && !iter.is_referent_alive();     //如果援用的对象还是不存活了,欧博体育下注则会去调用对应的ReferencePolicy判断该对象是时时要被回收     if (referent_is_dead &&         !policy->should_clear_reference(iter.obj(), _soft_ref_timestamp_clock)) {       if (TraceReferenceGC) {         gclog_or_tty->print_cr("Dropping reference (" INTPTR_FORMAT ": %s"  ") by policy",                                (void *)iter.obj(), iter.obj()->klass()->internal_name());       }       // Remove Reference object from list       iter.remove();       // Make the Reference object active again       iter.make_active();       // keep the referent around       iter.make_referent_alive();       iter.move_to_next();     } else {       iter.next();     }   }  ... } 

refs_lists中存放了本次GC发现的某种援用类型(虚援用、软援用、弱援用等),而

process_discovered_reflist步调的作用等于将不需要被回收的对象从refs_lists移撤退,refs_lists终末剩下的元素全是需要被回收的元素,终末会将其第一个元素赋值给上文提到过的Reference.java#pending字段。

备用皇冠

ReferencePolicy一共有4种兑现:NeverClearPolicy,AlwaysClearPolicy,LRUCurrentHeapPolicy,LRUMaxHeapPolicy。

其中NeverClearPolicy恒久复返false,代表恒久不回收SoftReference,在JVM中该类莫得被使用,AlwaysClearPolicy则恒久复返true,在referenceProcessor.hpp#setup步调中中不错诞生policy为AlwaysClearPolicy,至于什么时候会用到AlwaysClearPolicy,大家有兴味不错自行连系。

LRUCurrentHeapPolicy和LRUMaxHeapPolicy的should_clear_reference步调则是皆备相同:

皇冠客服飞机:@seo3687

bool LRUMaxHeapPolicy::should_clear_reference(oop p,                                              jlong timestamp_clock) {   jlong interval = timestamp_clock - java_lang_ref_SoftReference::timestamp(p);   assert(interval >= 0, "Sanity check");    // The interval will be zero if the ref was accessed since the last scavenge/gc.   if(interval <= _max_interval) {     return false;   }    return true; } 

timestamp_clock等于SoftReference的静态字段clock,

java_lang_ref_SoftReference::timestamp(p)对应是字段timestamp。如果前次GC后有调用SoftReference#get,interval值为0,不然为多少次GC之间的本领差。

皇冠集团

_max_interval则代表了一个临界值,它的值在LRUCurrentHeapPolicy和LRUMaxHeapPolicy两种战略中有互异。

幸运快艇真人百家乐
void LRUCurrentHeapPolicy::setup() {   _max_interval = (Universe::get_heap_free_at_last_gc() / M) * SoftRefLRUPolicyMSPerMB;   assert(_max_interval >= 0,"Sanity check"); }  void LRUMaxHeapPolicy::setup() {   size_t max_heap = MaxHeapSize;   max_heap -= Universe::get_heap_used_at_last_gc();   max_heap /= M;    _max_interval = max_heap * SoftRefLRUPolicyMSPerMB;   assert(_max_interval >= 0,"Sanity check"); } 

看到这里你就知说念SoftReference到底什么时候被被回收了,它和使用的战略(默许应该是LRUCurrentHeapPolicy),堆可用大小,该SoftReference上一次调用get步调的本领都相关联。

近日,仁爱礁附近的紧张局势再次成为焦点。菲律宾军舰在这片海域坐滩长达24年之久,严重侵犯了中国的主权。更令人不可容忍的是,有报道指出,菲律宾士兵对着中国海警船大笑并发出嘲讽,这种侮辱性的行为无疑给两国关系投下了一片阴影。面对此情况,我们需要冷静分析,并制定相应的对策。

WeakReference
public class WeakReference<T> extends Reference<T> {      public WeakReference(T referent) {         super(referent);     }      public WeakReference(T referent, ReferenceQueue<? super T> q) {         super(referent, q);     }  } 

不错看到,关于Soft references和Weak references clear_referent字段传入的都是true,这也顺应咱们的预期:对象不可达后,援用字段就会被置为null,然后对象就会被回收(关于软援用来说,如果内存填塞的话,在Phase 1,相关的援用就会从refs_list中被移除,到Phase 3时refs_list为空蚁集)。

但关于Final references和 Phantom references,clear_referent字段传入的是false,也就意味着被这两种援用类型援用的对象,如果莫得其他格外处理,只消Reference对象还存活,那援用的对象是不会被回收的。Final references和对象是否重写了finalize步调联系,不在本文分析界限之内,咱们接下来望望Phantom references。

不错看到WeakReference在Java层仅仅收受了Reference,莫得作念任何的转换。那referent字段是什么时候被置为null的呢?要搞明晰这个问题咱们再看下上文提到过的

process_discovered_reflist步调:

 

size_t ReferenceProcessor::process_discovered_reflist(   DiscoveredList               refs_lists[],   ReferencePolicy*             policy,   bool                         clear_referent,   BoolObjectClosure*           is_alive,   OopClosure*                  keep_alive,   VoidClosure*                 complete_gc,   AbstractRefProcTaskExecutor* task_executor) {  ...    //Phase 1:将通盘不存活然则还不可被回收的软援用从refs_lists中移除(唯独refs_lists为软援用的时候,这里policy才不为null)   if (policy != NULL) {     if (mt_processing) {       RefProcPhase1Task phase1(*this, refs_lists, policy, true /*marks_oops_alive*/);       task_executor->execute(phase1);     } else {       for (uint i = 0; i < _max_num_q; i++) {         process_phase1(refs_lists[i], policy,                        is_alive, keep_alive, complete_gc);       }     }   } else { // policy == NULL     assert(refs_lists != _discoveredSoftRefs,            "Policy must be specified for soft references.");   }    // Phase 2:   // 移除通盘指向对象还存活的援用   if (mt_processing) {     RefProcPhase2Task phase2(*this, refs_lists, !discovery_is_atomic() /*marks_oops_alive*/);     task_executor->execute(phase2);   } else {     for (uint i = 0; i < _max_num_q; i++) {       process_phase2(refs_lists[i], is_alive, keep_alive, complete_gc);     }   }    // Phase 3:   // 字据clear_referent的值决定是否将不存活对象回收   if (mt_processing) {     RefProcPhase3Task phase3(*this, refs_lists, clear_referent, true /*marks_oops_alive*/);     task_executor->execute(phase3);   } else {     for (uint i = 0; i < _max_num_q; i++) {       process_phase3(refs_lists[i], clear_referent,                      is_alive, keep_alive, complete_gc);     }   }    return total_list_count; }  void ReferenceProcessor::process_phase3(DiscoveredList&    refs_list,                                    bool               clear_referent,                                    BoolObjectClosure* is_alive,                                    OopClosure*        keep_alive,                                    VoidClosure*       complete_gc) {   ResourceMark rm;   DiscoveredListIterator iter(refs_list, keep_alive, is_alive);   while (iter.has_next()) {     iter.update_discovered();     iter.load_ptrs(DEBUG_ONLY(false /* allow_null_referent */));     if (clear_referent) {       // NULL out referent pointer       //将Reference的referent字段置为null,之后会被GC回收       iter.clear_referent();     } else {       // keep the referent around       //记号援用的对象为存活,该对象在此次GC将不会被回收       iter.make_referent_alive();     }     ...   }     ... } 

岂论是弱援用如故其他援用类型,将字段referent置null的操作都发生在process_phase3中,而具体行动是由clear_referent的值决定的。而clear_referent的值则和援用类型相关。

 

ReferenceProcessorStats ReferenceProcessor::process_discovered_references(   BoolObjectClosure*           is_alive,   OopClosure*                  keep_alive,   VoidClosure*                 complete_gc,   AbstractRefProcTaskExecutor* task_executor,   GCTimer*                     gc_timer) {   NOT_PRODUCT(verify_ok_to_handle_reflists());     ...   //process_discovered_reflist步调的第3个字段等于clear_referent   // Soft references   size_t soft_count = 0;   {     GCTraceTime tt("SoftReference", trace_time, false, gc_timer);     soft_count =       process_discovered_reflist(_discoveredSoftRefs, _current_soft_ref_policy, true,                                  is_alive, keep_alive, complete_gc, task_executor);   }    update_soft_ref_master_clock();    // Weak references   size_t weak_count = 0;   {     GCTraceTime tt("WeakReference", trace_time, false, gc_timer);     weak_count =       process_discovered_reflist(_discoveredWeakRefs, NULL, true,                                  is_alive, keep_alive, complete_gc, task_executor);   }    // Final references   size_t final_count = 0;   {     GCTraceTime tt("FinalReference", trace_time, false, gc_timer);     final_count =       process_discovered_reflist(_discoveredFinalRefs, NULL, false,                                  is_alive, keep_alive, complete_gc, task_executor);   }    // Phantom references   size_t phantom_count = 0;   {     GCTraceTime tt("PhantomReference", trace_time, false, gc_timer);     phantom_count =       process_discovered_reflist(_discoveredPhantomRefs, NULL, false,                                  is_alive, keep_alive, complete_gc, task_executor);   }     ... } 

不错看到,关于Soft references和Weak references clear_referent字段传入的都是true,这也顺应咱们的预期:对象不可达后,援用字段就会被置为null,然后对象就会被回收(关于软援用来说,如果内存填塞的话,在Phase 1,相关的援用就会从refs_list中被移除,到Phase 3时refs_list为空蚁集)。

但关于Final references和 Phantom references,clear_referent字段传入的是false,也就意味着被这两种援用类型援用的对象,如果莫得其他格外处理,只消Reference对象还存活,那援用的对象是不会被回收的。Final references和对象是否重写了finalize步调联系,不在本文分析界限之内,咱们接下来望望Phantom references。

PhantomReference

 

public class PhantomReference<T> extends Reference<T> {      public T get() {         return null;     }      public PhantomReference(T referent, ReferenceQueue<? super T> q) {         super(referent, q);     }  } 

不错看到虚援用的get步调恒久复返null,咱们看个demo。

public static void demo() throws InterruptedException {         Object obj = new Object();         ReferenceQueue<Object> refQueue =new ReferenceQueue<>();         PhantomReference<Object> phanRef =new PhantomReference<>(obj, refQueue);          Object objg = phanRef.get();         //这里拿到的是null         System.out.println(objg);         //让obj变成垃圾         obj=null;         System.gc();         Thread.sleep(3000);         //gc后会将phanRef加入到refQueue中         Reference<? extends Object> phanRefP = refQueue.remove();          //这里输出true         System.out.println(phanRefP==phanRef);     } 

从以上代码中不错看到,虚援用大致在指向对象不可达时得到一个'示知'(其实通盘收受References的类都有这个功能),需要闪耀的是GC完成后,phanRef.referent依然指向之前创建Object,也等于说Object对象一直没被回收!

而形成这一时事的原因在上一末节末尾还是说了:关于Final references和 Phantom references,clear_referent字段传入的时false,也就意味着被这两种援用类型援用的对象,如果莫得其他格外处理,在GC中是不会被回收的。

关于虚援用来说,从refQueue.remove();得到援用对象后,不错调用clear步调强行撤消援用和对象之间的关系,使得对象下次不错GC时不错被回收掉。

End

针对著作开头提议的几个问题,看完分析,咱们还是能给出回报:

1.咱们时时在网上看到软援用的先容是:在内存不及的时候才会回收,那内存不及是若何界说的?为什么才叫内存不及?

软援用会在内存不实时被回收,内存不及的界说和该援用对象get的本领以及面前堆可用内存大小都相关联,斟酌公式在上文中也还是给出。

2.网上关于虚援用的先容是:形同虚设,与其他几种援用都不同,虚援用并不会决定对象的生命周期。主要用来追踪对象被垃圾回收器回收的行径。竟然是这么吗?

严格的说,虚援用是会影响对象生命周期的,如果不作念任那里理,只消虚援用不被回收,那其援用的对象恒久不会被回收。是以一般来说,从ReferenceQueue中赢得PhantomReference对象后,如果PhantomReference对象不会被回收的话(比如被其他GC ROOT可达的对象援用),需要调用clear步退换除PhantomReference和其援用对象的援用关系。

3.虚援用在Jdk中有哪些场景下用到了呢?

DirectByteBuffer中是用虚援用的子类Cleaner.java来兑现堆外内存回收的,后续会写篇著作来说说堆外内存的里里外外。