字节码深入分析finally块对return再次来到值的影响
分类:long8

CPU通过时间片分配算法来循环实行义务,当前职务实施一个岁月片后会切换成下多个任务。可是,在切换前会保存上贰个义务的景色,以便后一次切换回那一个职分时,能够再加载这些任务的图景。所以职分从保存到再加载的历程正是二次上下文切换。

继上一篇字节码解析finally块对return重临值的影响,好四人对有些变量表和操作数栈之间的关系搞不清楚,上面通过图解来描述局部变量表和操作数栈直接的涉及。

synchronized能够确认保障措施可能代码块在运行时,同临时刻独有七个办法能够进来惠临界区,同不平时间它还是能保险分享变量的内部存款和储蓄器可知性Java中每三个指标都能够看做锁,那是synchronized实现同台的底蕴。

long88龙8国际娱乐,继上一篇HashMap完结中文分词器后,对Trie Tree的奇怪,又采取Trie Tree实现了下中文分词器。效用比HashMap达成的分词器更加高。

直白步向正题。看如下代码:

那就像大家同不常间读两本书,当大家在读一本丹麦语的技能书时,开采有个别单词不认知,于是便张开中国和俄罗丝语字典,可是在放下斯洛伐克(Slovak)语手艺书在此以前,大脑必得先记住那本书读到了稍稍页的第多少行,等查完单词之后,能够持续读那本书。那样的切换是会影响读书效用的,同样上下文切换也会耳濡目染三二十四线程的实践进度。

透过下边这段代码来注解JVM基于栈的举行原理

synchronized 常见的三种用法如下:

Trie Tree,又称单词字典树、查找树,是一种树形结构,是一种哈希树的变种。标准应用是用于总括和排序大批量的字符串,所以时常被搜寻引擎系统用于文书词频总括。它的亮点是:最大限度地减小无谓的字符串相比,查询效能比哈希表高。

public int test(){ int i=0; try { i=1; return i; } catch (Exception e) { i=2; return i; }finally{ i=3; }}

字节码深入分析finally块对return再次来到值的影响,深刻精通。1、发挥多管理器的兵不血刃手艺。能够使多线程在差异的CPU上实施,丰盛利用多CPU的优势。2、能够尽量的使用cpu空闲时间。例如当程序在等待有个别IO操作,达成时,CPU将出于空闲状态,那时CPU能够运作别的线程,提升CPU的利用率。3、简化开采流程,能够运用不一致的线程开垦差别的事体职能,代码逻辑更鲜明。

4. public static int add(int a, int b) {5. int c = 0;6. c = a + b;7. return c;8. }
  1. 日常来讲同步方法,锁是当前实例对象

它有3个主题个性:

信赖有一点点经验的技术员一眼就会表露再次回到的结果为1,可是你真的知道重回的结果为何为1吧?上边大家由此剖析下当前格局的字节码,来注脚为什么。

1、安全性难点。安全性难点莫过于正是线程安全性,那一点是极度复杂的,因为在一直分化步的情事下,八个线程同期实行,实践顺序是不足预测的,恐怕会师世意外的结果。2、活跃性难题。关怀的是某件精确事情最后会发出。由于线程的引进,会出现A线程在等待线程B释放其负有的财富,而B线程恒久都不自由该财富,那么A就永恒的一筹莫展试行。3、质量难题。在八线程中,线程调整器一时挂起活跃线程转而运作另一个线程就能产出上下文切换,会保留和复苏实践上下文,让cpu会支出在线程调节上并不是运转商。

翻开字节码的授命:javap -verbose ByteCode.class

  1. 静态同步方法,锁是近期类的class对象
  2. 同步方法块,锁是括号里面包车型客车目的
  1. 根节点不分包字符,除根节点外每二个节点都只满含二个字符。
  2. 从根节点到某一节点,路线上经过的字符连接起来,为该节点对应的字符串。
  3. 每一个节点的全数子节点饱含的字符都不相同样。

翻开字节码命令:javap -verbose class文件

知识点简单概要:看如下字节码需求轻松明白下栈的结构。栈包含:局地变量表、操作数栈、动态连接、方法说话等。下边字节码首借使对操作栈和局变量表的操作。

Daemon线程是一种辅助型线程,因为它至关心重视要被视作程序中后台调整以及援助性职业。那代表,当三个Java设想机中不设有非Daemon线程的时候,Java设想机将会退出。能够透过调用Thread.setDaemon将线程设置为Daemon线程。

add方法的字节码如下:

因而如下代码来剖析下synchronized 获取的是哪位目的的锁

long88龙8国际娱乐 1Trie Tree

 stack=1, locals=5, args_size=1 0: iconst_0 将常量0压入到操作栈顶 1: istore_1 将栈顶元素0存储到局部变量表中的第二个slot中  i=0 2: iconst_1 将常量1压入到操作栈顶 3: istore_1 将栈顶元素1存储到局部变量表中的第二个slot中  i=1 4: iload_1 将局部变量中第二个变量  压入到操作栈顶 5: istore 4 将栈顶元素1存储到局部变量表中的第四个slot中  7: iconst_3 将常量3压入到操作栈顶 8: istore_1 将栈顶元素3存储到局部变量表中的第二个slot中  i=3 9: iload 4 将局部变量中第四个变量  压入到操作栈顶 11: ireturn 返回操作栈顶值,这时操作栈中栈顶值为1。 12: astore_2 将栈顶元素存储到局部变量表的第三个slot中 13: iconst_2 将常量2压入到操作栈顶 14: istore_1 将栈顶元素2存储到局部变量表中的第二个slot中  i=2 15: iload_1 将局部变量中第二个变量  压入到操作栈顶 16: istore 4 将栈顶元素2存储到局部变量表中的第四个slot中  18: iconst_3 将常量3压入到操作栈顶 19: istore_1 将栈顶元素3存储到局部变量表中的第二个slot中  i=3 20: iload 4 将局部变量中第四个变量  压入到操作栈顶 22: ireturn 返回操作栈顶值,这时操作栈中栈顶值为2。 23: astore_3 将栈顶元素(其它异常,Exception之外的)存储到局部变量表的第四个slot中 24: iconst_3 将常量3压入到操作栈顶 25: istore_1 将栈顶元素3存储到局部变量表中的第二个slot中  i=3 26: aload_3 将局部变量中第四个变量  压入到操作栈顶 27: athrow 抛出栈顶元素 无返回值

小心 Daemon属性供给在起步线程以前安装,不能够在运维线程之后设置。

 public static int add; descriptor: I //描述方法参数为两个int类型的变量和方法的返回类型是int的 flags: ACC_PUBLIC, ACC_STATIC //修饰方法public和static Code: stack=2, locals=3, args_size=2 //操作数栈深度为2,本地变量表容量为3,参数个数为2 0: iconst_0 //将int值0压栈 1: istore_2 //将int值0出栈,存储到第三个局部变量中 2: iload_0 //将局部变量表中第一个变量10压栈 3: iload_1 //将局部变量表中第一个变量20压栈 4: iadd //将操作数栈顶两个int数弹出,相加后再压入栈中 5: istore_2 //将栈顶的int数弹出,存储到第三个局部变量中 6: iload_2 //将局部变量表中第三个变量压栈 7: ireturn //返回栈中数字30 LineNumberTable: line 5: 0 //代码第5行对应字节码第0行 line 6: 2 //代码第6行对应字节码第2行 line 7: 6 //代码第7行对应字节码第6行 LocalVariableTable: Start Length Slot Name Si 0 8 0 a I //a占用第1个solt 0 8 1 b I //b占用第2个solt 2 6 2 c I //c占用第3个solt
public class SynTest { private static List<String> list = new ArrayList<String>(); //当前实例的锁 public synchronized void add1{ list.add; } //SynTest.class 锁 public static synchronized void add2{ list.add; } //SynTest.class 锁 public void add3{ synchronized(SynTest.class){ list.add; } } //当前实例的锁 public void add4{ synchronized{ list.add; } }}

从根结点起头叁次搜索,比方寻觅获得要寻觅关键词的首先个字符,并依照该字符选拔相应的子树并转到该子树继续开展搜寻; 在对应的子树上,猎取要搜索关键词的第一个字符,并一发选取相应的子树实行检索。 迭代进程…… 在直到剖断树节点的isEnd节点为true则查找截止,然后开掘isEnd=true,则甘休查找。

stack=1, locals=5, args_size=1

Daemon线程被用作实现扶助性职业,但是在Java虚构机退出时Daemon线程中的finally块并不一定会实行,示举例下代码所示。

基于上边字节码画出上面局地变量表和操作数栈之间的操作关系。

常常同步方法,锁是日前实例对象add1 主意是synchronized的第一种用法,因为它是经常同步方法,所以取妥贴前实例的锁。add2 艺术是synchronized的第两种用法,因为它是静态同步方法,所以得到SynTest.class的锁。add3 方法是synchronized的第二种用法。钦定锁:SynTest.class。add4 方法是synchronized的第二种用法。钦赐锁:this。

上边用java轻巧实现

  • stack=1:操作栈的深浅
  • locals=5:局地变量表中5个slot,每种slot存款和储蓄能四个变量(long、double 必要四个slot存款和储蓄)
public class Daemon { public static void main(String[] args) { Thread thread = new Thread(new DaemonRunner(), "DaemonRunner"); thread.setDaemon; thread.start(); } static class DaemonRunner implements Runnable { @Override public void run() { try { SleepUtils.second; } finally { System.out.println("DaemonThread finally run."); } } }}

long88龙8国际娱乐 2部分变量表和操作数栈关系

结论:

package cn.com.infcn.algorithm;import java.util.HashMap;import java.util.LinkedList;import java.util.List;import java.util.Map;import java.util.Map.Entry;/** * jijs * 正向最大匹配 */public class TrieTreeDemo { static class Node { //记录当前节点的字 char c; //判断该字是否词语的末尾,如果是则为false boolean isEnd; //子节点 List<Node> childList; public Node { super(); this.c = c; isEnd = false; childList = new LinkedList<Node>(); } //查找当前子节点中是否保护c的节点 public Node findNode{ for(Node node : childList){ if(node.c == c){ return node; } } return null; } } static class TrieTree{ Node root = new Node; //构建Trie Tree public void insert(String words){ char[] arr = words.toCharArray(); Node currentNode = root; for (char c : arr) { Node node = currentNode.findNode; //如果不存在该节点则添加 if(node == null){ Node n = new Node; currentNode.childList.add; currentNode = n; }else{ currentNode = node; } } //在词的最后一个字节点标记为true currentNode.isEnd = true; } //判断Trie Tree中是否包含该词 public boolean search(String word){ char[] arr = word.toCharArray(); Node currentNode = root; for (int i=0; i<arr.length; i++) { Node n = currentNode.findNode; if(n != null){ currentNode = n; //判断是否为词的尾节点节点 if{ if(n.c == arr[arr.length-1]){ return true; } } } } return false; } //最大匹配优先原则 public Map<String, Integer> tokenizer(String words){ char[] arr = words.toCharArray(); Node currentNode = root; Map<String, Integer> map = new HashMap<String, Integer>(); //记录Trie Tree 从root开始匹配的所有字 StringBuilder sb = new StringBuilder();; //最后一次匹配到的词,最大匹配原则,可能会匹配到多个字,以最长的那个为准 String word=""; //记录记录最后一次匹配坐标 int idx = 0; for (int i=0; i<arr.length; i++) { Node n = currentNode.findNode; if(n != null){ sb.append; currentNode = n; //匹配到词 if{ //记录最后一次匹配的词 word = sb.toString(); //记录最后一次匹配坐标 idx = i; } }else{ //判断word是否有值 if(word!=null && word.length{ Integer num = map.get; if(num==null){ map.put; }else{ map.put(word, num+1); } //i回退到最后匹配的坐标 i=idx; //从root的开始匹配 currentNode = root; //清空匹配到的词 word = null; //清空当前路径匹配到的所有字 sb = new StringBuilder(); } } //已匹配到最后一位 if(i==arr.length-1){ if(word!=null && word.length{ Integer num = map.get; if(num==null){ map.put; }else{ map.put(word, num+1); } } } } return map; } } public static void main(String[] args) { TrieTree tree = new TrieTree(); tree.insert; tree.insert; tree.insert; tree.insert; tree.insert; String word = "中国"; //查找该词是否存在 Trid Tree 中 boolean flag = tree.search; if{ System.out.println("Trie Tree 中已经存在"); }else{ System.out.println("Trie Tree 不包含"); } //分词 Map<String, Integer> map = tree.tokenizer("中国人民,中国首都是北京,中关村在海淀区,中国北京天安门。中国人"); for (Entry<String, Integer> entry : map.entrySet { System.out.println(entry.getKey()+":"+entry.getValue; } }}
  1. this变量
  2. i 变量
  3. e 变量(Exception)
  4. Exception之外那一个的变量
  5. 前段时间存款和储蓄变量(再次来到值从有时存储中回到的)

本文由long8发布于long8,转载请注明出处:字节码深入分析finally块对return再次来到值的影响

上一篇:没有了 下一篇:没有了
猜你喜欢
热门排行
精彩图文