技术管理:都是既需要“带人”,又需要“做事”,也就是对团队和业务都要关心。
管理都做哪些事呢?我会说:“主要做好三件事:带人、做事、看方向,当然,做好这些事都要基于良好的角色认知和管理沟通。”
1. 角色认知马车模型
第一个角度,从工作职责来看。确保这辆马车良好地行驶在正确的方向上
第二个角度,从负责对象来看,需要对上级负责;还得关心团队成员的发展和成长,对下级负责。
第三个角度,管理者是目标和结果导向的,他们时时关心目标和前进方向,盯着“远方的目标”,因为他们得决定要带着团队去哪里。
第四个角度,管理者要做成一项工作,需要看方向的、带人的、做事的更加多维和立体的能力。
第五个角度,从任务来源来看。有上级工作的拆解和安排,但更多是靠自己筹划,然后和上级去沟通确认,从被动“等活儿”变为主动规划。
第六个角度,管理者的工作清单涵盖了整体团队的工作,靠自己一个人是无论如何都做不完的,因此主要是依靠团队来完成。
第七个角度,从合作维度来看。合作的维度变得非常立体:下级、上级、平级;
第八个角度,从和团队成员的合作关系来看。之前做工程师的时候,和大家都是平等竞合关系,以合作为主,也有“竞”的成分 ...
字符串匹配是计算机的基本任务之一。
举例来说,有一个字符串”BBC ABCDAB ABCDABCDABDE”,我想知道,里面是否包含另一个字符串”ABCDABD”?
许多算法可以完成这个任务,Knuth-Morris-Pratt算法(简称KMP)是最常用的之一。它以三个发明者命名,起头的那个K就是著名科学家Donald Knuth。
这种算法不太容易理解,网上有很多解释,但读起来都很费劲。直到读到Jake Boxer的文章,我才真正理解这种算法。下面,我用自己的语言,试图写一篇比较好懂的KMP算法解释。
首先,字符串”BBC ABCDAB ABCDABCDABDE”的第一个字符与搜索词”ABCDABD”的第一个字符,进行比较。因为B与A不匹配,所以搜索词后移一位。
因为B与A不匹配,搜索词再往后移。
就这样,直到字符串有一个字符,与搜索词的第一个字符相同为止。
接着比较字符串和搜索词的下一个字符,还是相同。
直到字符串有一个字符,与搜索词对应的字符不相同为止。
这时,最自然的反应是,将搜索词整个后移一位,再从头逐个比较。这样做虽然可行 ...
Dapper,大规模分布式系统的跟踪系统作者:Benjamin H. Sigelman, Luiz Andr´e Barroso, Mike Burrows, Pat Stephenson, Manoj Plakal, Donald Beaver, Saul Jaspan, Chandan Shanbhag概述当代的互联网的服务,通常都是用复杂的、大规模分布式集群来实现的。互联网应用构建在不同的软件模块集上,这些软件模块,有可能是由不同的团队开发、可能使用不同的编程语言来实现、有可能布在了几千台服务器,横跨多个不同的数据中心。因此,就需要一些可以帮助理解系统行为、用于分析性能问题的工具。
Dapper–Google生产环境下的分布式跟踪系统,应运而生。那么我们就来介绍一个大规模集群的跟踪系统,它是如何满足一个低损耗、应用透明的、大范围部署这三个需求的。当然Dapper设计之初,参考了一些其他分布式系统的理念,尤其是Magpie和X-Trace,但是我们之所以能成功应用在生产环境上,还需要一些画龙点睛之笔,例如采样率的使用以及把代码植入限制在一小部分公共库的改造上。
自从Dapper发展 ...
这类问题网上很多答案,大概意思呢如下:ES 是基于 Lucene 的全文检索引擎,它会对数据进行分词后保存索引,擅长管理大量的索引数据,相对于 MySQL 来说不擅长经常更新数据及关联查询。
说的不是很透彻,没有解析相关的原理;不过既然反复提到了索引,那我们就从索引的角度来对比下两者的差异。
MySQL 索引先从 MySQL 说起,索引这个词想必大家也是烂熟于心,通常存在于一些查询的场景,是典型的空间换时间的案例。以下内容以 InnoDB 引擎为例。
常见的数据结构假设由我们自己来设计 MySQL 的索引,大概会有哪些选择呢?
①散列表首先我们应当想到的是散列表,这是一个非常常见且高效的查询、写入的数据结构,对应到 Java 中就是 HashMap。
这个数据结构应该不需要过多介绍了,它的写入效率很高 O(1),比如我们要查询 id=3 的数据时,需要将 3 进行哈希运算,然后再这个数组中找到对应的位置即可。
但如果我们想查询 1≤id≤6 这样的区间数据时,散列表就不能很好的满足了,由于它是无序的,所以得将所有数据遍历一遍才能知道哪些数据属于这个区间。
②有序数组
有序数 ...
引用处:JAVA8如何妙用Optional解决NPE问题详解
引言
NPE(NullPointerException)是调试程序最常见的异常。google一下有很多关于方法到底应该返回null还是new一个空对象的讨论。
在文章的开头,先说下NPE问题,NPE问题就是,我们在开发中经常碰到的NullPointerException.假设我们有两个类,他们的UML类图如下图所示在这种情况下,有如下代码:
12user.getAddress().getProvince();
这种写法,在user为null时,是有可能报NullPointerException异常的。为了解决这个问题,于是采用下面的写法:
1234567if(user!=null){ Address address = user.getAddress(); if(address!=null){ String province = address.getProvince(); }}
这种写法是比较丑陋的,为了避免上述丑陋的写法,让丑陋的设计变得优雅。JAVA8提供了Optional类 ...
0、前言
Java程序中 User user = new User();的代码在执行过程中,JVM究竟做了哪些工作?
1、Java类对象的创建过程
Java对象保存在内存中时,主要由三部分组成:对象头、实例数据、对齐填充字段,所以Java对象创建的过程实际上是对这三部分进行配置、补充和初始化的过程。
注:对齐填充字段:在JVM中,要求对象占用内存的大小应该是8bit的倍数,这个信息是用来补齐8bit的,无其他作用
1.1、类加载检查阶段
虚拟机遇到一条new指令时,首先将去检查这个指令的参数是否能在常量池中定位到这个类的符号引用,并且检查这个符号引用所代表的类是否已被加载过、连接过和初始化过。如果没有则必须先执行相应的类加载过程。
1.2、分配内存
类加载检查通过后,JVM将为新创建对象分配内存。对象所需的内存大小在类加载完成后便可以确定。所以,为对象分配内存空间相当于把确定大小的内存从Java堆中划分出来。分配方式有”指针碰撞”和”空闲列表”两种,选择哪种分配方式由Java堆是否规整决定,而Java堆是否规整又由所采用的垃圾收集器是否具有压缩整理功能所决定(标记-清楚不规 ...
前言
本文继续【Java并发之synchronized关键字深度解析(一)】一文而来,着重介绍synchronized几种锁的特性。
一、对象头结构及锁状态标识
synchronized关键字是如何实现的给对象加锁?首先我们要了解一下java中对象的组成。java中的对象由3部分组成,第一部分是对象头,第二部分是实例数据,第三部分是对齐填充。
对齐填充:jvm规定对象的起始内存地址必须是8字节的整数倍,如果不够的话就用占位符来填充,此部分占位符就是对齐填充;
实例数据:实例数据是对象存储的真正有效的信息-对象的成员变量信息(包括继承自父类的);
对象头:对象头由两部分组成,第一部分是对象的运行时数据(Mark Word),包括哈希吗、锁偏向标识、锁类型、GC分代年龄、偏向线程id等;第二部分是对象的类型指针(Kclass Word),用于去堆中定位对象的实例数据和方法区中的类型数据。java对象的公共特性都在对象头中存放。
对象头存储内容如下所示(以64位操作系统为例):
123456789101112131415|--------------- ...
前言Java提供了种类丰富的锁,每种锁因其特性的不同,在适当的场景下能够展现出非常高的效率。本文旨在对锁相关源码(本文中的源码来自JDK 8和Netty 3.10.6)、使用场景进行举例,为读者介绍主流锁的知识点,以及不同的锁的适用场景。
Java中往往是按照是否含有某一特性来定义锁,我们通过特性将锁进行分组归类,再使用对比的方式进行介绍,帮助大家更快捷的理解相关知识。下面给出本文内容的总体分类目录:
1. 乐观锁 VS 悲观锁乐观锁与悲观锁是一种广义上的概念,体现了看待线程同步的不同角度。在Java和数据库中都有此概念对应的实际应用。
先说概念。对于同一个数据的并发操作,悲观锁认为自己在使用数据的时候一定有别的线程来修改数据,因此在获取数据的时候会先加锁,确保数据不会被别的线程修改。Java中,synchronized关键字和Lock的实现类都是悲观锁。
而乐观锁认为自己在使用数据时不会有别的线程修改数据,所以不会添加锁,只是在更新数据的时候去判断之前有没有别的线程更新了这个数据。如果这个数据没有被更新,当前线程将自己修改的数据成功写入。如果数据已经被其他线程更新,则根据不同的实现 ...
MapDB****特性
mapdb是一个内嵌的纯java的数据库,提供了并发的HashMap、TreeMap、Queue,可以基于堆外或者磁盘来存储数据。用户可以通过配置选择不同的机制来提高性能,比如可以配置多种不同的cache来减少反序列化的开销,提高读取性能;可以开启异步写引擎,使用后台线程来进行序列化和存储更新,来提高插入性能,减少rt。它支持ACID事务、MVCC隔离。它的代码精简,只有一个jar包,无其他依赖,总共才200kb。并且高度模块化,用户可以很容易的扩展,添加新特性。
MapDB****架构
从下面的类图,可以看出MapDB的整体脉络,它采用分层的设计,针对接口编程。上层只依赖下层的接口,具体实现可替换。顶层是针对用户的接口,也就是各种数据结构的接口。中间层是存储引擎Engine, 提供简单的key value接口,是MapDB的核心模块,管理对象为记录,通过记录id操作,用户不能直接使用。底层的是Volume,是对原始存储媒介的抽象,MapDB提供堆内、堆外、磁盘等存储媒介。这样的分层设计,使得MapDB的模块清晰,每一层都可以很容易的扩展,只需要实现接口即可。
...
MySQL和Lucene都可以对数据构建索引并通过索引查询数据,一个是关系型数据库,一个是构建搜索引擎(Solr、ElasticSearch)的核心类库。两者的索引(index)有什么区别呢?以前写过一篇《Solr与MySQL查询性能对比》,只是简单的对比了下查询性能,对于内部原理却没有解释,本文简单分析下两者的索引区别。
MySQL索引实现
在MySQL中,索引属于存储引擎级别的概念,不同存储引擎对索引的实现方式是不同的,本文主要讨论MyISAM和InnoDB两个存储引擎的B+Tree索引实现方式(HASH索引不能使用范围查询,只支持等值比较查询,不在此文章讨论)。
MyISAM索引实现
MyISAM引擎使用B+Tree作为索引结构,叶节点的data域存放的是数据记录的地址。下图是MyISAM索引的原理图:
图1是一个MyISAM表的主索引(Primary key)示意。可以看出MyISAM的索引文件仅仅保存数据记录的地址。在MyISAM中,主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求key是唯一的,而辅助索引的key可以重复。B+Tree的所 ...