首页 文章 精选 留言 我的

精选列表

搜索[智能解析],共10007篇文章
优秀的个人博客,低调大师

Intent解析

一.综述 intent对象是一个信息桶。它包含了接收它的组件感兴趣的信息(如:携带的动作和数据),附加Android系统感兴趣的信息(如:处理intent和启动目标Activity指令的组件的类别) 程序的3个核心组件——Activity、services、广播接收器——是通过intent传递消息的。intent消息对于运行时绑定不同的组件是很方便的,这些组件可以是同一个程序也可以是不同的。一个intent对象,是一个被动的数据结构,它保存了一个操作的抽象描述——或通常是一个广播的实例,一些发生的事情的描述,一个通知。传递intent到不同组件的机制是互不相同的。 intent对象是传递给Context.startActivity() 或Activity.startActivityForResult() 以启动Activity或是让一个存在的Activity做些事情。(也可以传递给Activity.setResult()来返回Activity的信息,这个函数叫startActivityForResult()。) intent对象传递给函数来初始化一个service或是分发一个新的指令给一个正在进行的service。同样,intent传递给来建立一个在调用组件和目标service间的联系。如果一个service没有运行,它可以开始它。 intent可以传递给任何广播函数(如:Context.sendBroadcast()、Context.sendOrderedBroadcast()、 Context.sendStickyBroadcast()),intent被分派给所有感兴趣的广播接收者。很多广播源在系统内核里。 Android系统会寻找合适的Activity、service或设置广播接收器来响应intent,在需要的时候实例化它们。在消息系统里没有交叠:广播intent仅仅分派给广播接收器,不会分派给Activity或service。一个intent分派给startActivity()仅仅分派给Activity,不会分派给service或广播接收器,等等。 二.Intent关联的东西 @1四大组件Activity,Brocast,Service,Receiver,intent可以在四大组件中传递消息和数据。 @2动作Action,通过 setAction()函数设置,通过getAction()函数读取 @3数据Data,数据的URI和MIME类型的数据,setData() 函数指定数据作为一个URI, setType()指定它为一个MIME类型,setDataAndType()指定它是URI也是MIME类型。 getData()函数读取URI, getType()读取类型 @4类型addCategory() 放置一个intent里的类别,removeCategory()删除之前添加的,getCategories()获取当前所有的类别。 @5扩展,intent有一系列的put...() 函数来插入各种类型的数据和一系列get...()函数来获取各种类型的数据。对Bundle 对象,这些函数是并行的。事实上,可以使用函数putExtras()和函数getExtras()来把数据作为Bundle读取、插入 @6标志,各种排序的标志。指示Android如何启动Activity(例如:Activity属于那个任务)启动后如何处理(例如:是否属于现在Activity 的列表)。这些标志在intent类里定义。 和平台相关的Android系统和程序使用intent来发送系统的广播、激活系统定义的组件。和intent激活系统组件相关的内容,在list of intents 三.Intent的分类 1.显示意图Intent /** *显示意图开启activity * *@paramview*/ publicvoidsee(Viewview){ Intentintent=newIntent(this,MyActivity.class); startActivity(intent); } 2.隐式意图Intent 实例程序: @1开启本应用的Activity =Intent("com.market.textintent.MY""huihui:"+123456),"pp/my" <?xmlversion="1.0"encoding="utf-8"?><manifestxmlns:android="http://schemas.android.com/apk/res/android" package="com.market.testintent"> <uses-permissionandroid:name="android.permission.SEND_SMS"/> <applicationandroid:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activityandroid:name="market.testintent.MainActivity"> <intent-filter> <actionandroid:name="android.intent.action.MAIN"/> <categoryandroid:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <activityandroid:name="market.testintent.MyActivity"> <intent-filter> <actionandroid:name="com.market.textintent.MY"/> <categoryandroid:name="android.intent.category.DEFAULT"/> <dataandroid:scheme="huihui"/> <dataandroid:mimeType="pp/my"/> </intent-filter> </activity> </application></manifest> <?xmlversion="1.0"encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:gravity="center_horizontal" android:padding="20dp" android:layout_height="match_parent"> <TextViewandroid:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:text="测试Intent"/> <Buttonandroid:onClick="send" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="发短信"/> <Buttonandroid:onClick="start" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="startMyActivity"/> <Buttonandroid:onClick="see" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="显示意图"/></LinearLayout> @2开启系统应用Activity /** *y隐式意图发短信 * *@paramview*/ publicvoidsend(Viewview){ Intentintent=newIntent(); intent.setAction(Intent.ACTION_VIEW); intent.addCategory(Intent.CATEGORY_DEFAULT); intent.setType("vnd.android-dir/mms-sms"); intent.putExtra("sms_body","美女,你吃饭了没?"); startActivity(intent); } 短信应用清单文件activity配置 本文转自lzwxx 51CTO博客,原文链接:http://blog.51cto.com/13064681/1943366

优秀的个人博客,低调大师

CoordinatorLayout解析

CoordinatorLayout作为“super-powered FrameLayout”基本实现两个功能: 1、作为顶层布局 2、调度协调子布局 CoordinatorLayout使用新的思路通过协调调度子布局的形式实现触摸影响布局的形式产生动画效果。CoordinatorLayout使用的时候通常和AppBarLayout搭配使用。在AppBarLayout里面的View,通过app:layout_scrollFlags属性来控制滚动时候的表现,其中有4种Flag的类型: scroll: 所有想滚动出屏幕的view都需要设置这个flag,没有设置这个flag的view将被固定在屏幕顶部。例如,TabLayout 没有设置这个值,将会停留在屏幕顶部。 enterAlways: 设置这个flag时,向下的滚动都会导致该view变为可见,启用快速“返回模式”。 enterAlwaysCollapsed: 这个flag定义的是何时进入(已经消失之后何时再次显示)。当你的视图已经设置minHeight属性又使用此标志时,你的视图只能在到达这个最小高度的时候开始显示,只有当滚动视图到达顶部时才扩大到完整高度。 exitUntilCollapsed: 当你定义了一个minHeight,这个view将在滚动到达这个最小高度的时候消失。 系统(Support V7)提供了AppBarLayout.Behavior、 AppBarLayout.ScrollingViewBehavior,、FloatingActionButton.Behavior和SwipeDismissBehavior<V extends View> 等。 使用CoordinatorLayout需要在Gradle加入Support Design Library,例如: compile 'com.android.support:design:22.2.1' CoordinatorLayout实现了多种Material Design中提到的滚动效果。目前这个框架提供了几种不用写动画代码就能工作的方法,这些效果包括: 一、CoordinatorLayout与FloatingActionButton让浮动操作按钮上下滑动,为Snackbar留出空间 FloatingActionButton是最简单的使用CoordinatorLayout的例子,FloatingActionButton默认使用FloatingActionButton.Behavior。 CoordinatorLayout可以用来配合浮动操作按钮的layout_anchor和layout_gravity属性创造出浮动效果。 只要使用CoordinatorLayout作为基本布局,将自动产生向上移动的动画。浮动操作按钮有一个默认的 behavior来检测Snackbar的添加并让按钮在Snackbar之上呈现上移与Snackbar等高的动画。 当Snackbar在显示的时候,往往出现在屏幕的底部。为了给Snackbar留出空间,浮动操作按钮需要向上移动。 定义布局文件: <?xml version="1.0" encoding="utf-8"?><android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:fitsSystemWindows="true"tools:context=".activity.MainActivity1"> <android.support.design.widget.FloatingActionButtonandroid:id="@+id/fab"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="bottom|end"android:layout_margin="@dimen/fab_margin"android:src="@android:drawable/ic_dialog_email" /></android.support.design.widget.CoordinatorLayout> CoordinatorLayout作为“super-powered FrameLayout”,设置子视图的 android:layout_gravity属性控制位置。 MainActivity.java如下: @Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main1);FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab_main1);fab.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) { Snackbar.make(view, "FAB", Snackbar.LENGTH_LONG) .setAction("cancel", new View.OnClickListener() {@Overridepublic void onClick(View v) {//这里的单击事件代表点击消除Action后的响应事件} }) .show();} });} 效果如下: 二、CoordinatorLayout与AppBarLayout 2.1使用ToolBar 为了ToolBar可以滚动,我们必须使用容器布局 AppBarLayout来让Toolbar响应滚动事件。然后,我们需要定义AppBarLayout与滚动视图之间的联系。在RecyclerView或者任意支持嵌套滚动的view比如NestedScrollView上添加app:layout_behavior。support library包含了一个特殊的字符串资源@string/appbar_scrolling_view_behavior,它和AppBarLayout.ScrollingViewBehavior相匹配,用来通知AppBarLayout 这个特殊的view何时发生了滚动事件,这个behavior需要设置在触发事件(滚动)的view之上。 布局文件: <?xml version="1.0" encoding="utf-8"?><android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".activity.MainActivity2"> <android.support.design.widget.AppBarLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> <android.support.v7.widget.Toolbarandroid:id="@+id/toolbar_main2"android:layout_width="match_parent"android:layout_height="?attr/actionBarSize"android:background="?attr/colorPrimary"app:layout_scrollFlags="scroll|enterAlways"app:popupTheme="@style/ThemeOverlay.AppCompat.Light" /> </android.support.design.widget.AppBarLayout> <android.support.v7.widget.RecyclerViewandroid:id="@+id/recycle_main2"android:layout_width="match_parent"android:layout_height="match_parent"app:layout_behavior="@string/appbar_scrolling_view_behavior" /> <android.support.design.widget.FloatingActionButtonandroid:id="@+id/fab_main2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="bottom|end"android:layout_margin="@dimen/fab_margin"android:src="@android:drawable/ic_dialog_email" /></android.support.design.widget.CoordinatorLayout> 当CoordinatorLayout发现RecyclerView中定义了这个属性,它会搜索自己所包含的其他view,看看是否有设置了app:layout_scrollFlags属性与这个 behavior相关联。AppBarLayout.ScrollingViewBehavior描述了RecyclerView与 AppBarLayout之间的依赖关系。RecyclerView的任意滚动事件都将触发AppBarLayout或者AppBarLayout里面 view的改变。 AppBarLayout里面定义的view只要设置了app:layout_scrollFlags属性,就可以在RecyclerView滚动事件发生的时候被触发: <android.support.design.widget.AppBarLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> <android.support.v7.widget.Toolbarandroid:id="@+id/toolbar_main2"android:layout_width="match_parent"android:layout_height="?attr/actionBarSize"android:background="?attr/colorPrimary"app:layout_scrollFlags="scroll|enterAlways"app:popupTheme="@style/ThemeOverlay.AppCompat.Light" /></android.support.design.widget.AppBarLayout> app:layout_scrollFlags属性里面必须至少启用scroll这个flag,这样这个view才会滚动出屏幕,否则它将一直固定在顶部。 Activity类如下: @Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main2);Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar_main2);setSupportActionBar(toolbar);RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycle_main2);LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);recyclerView.setLayoutManager(linearLayoutManager);String[] titles = new String[20]; for (int i = 0; i < 20; i++) titles[i] = "item " + i;mAdapter=new RecyclerViewAdapter(this,titles);recyclerView.setAdapter(mAdapter);FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab_main2);fab.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) { Snackbar.make(view, "FAB", Snackbar.LENGTH_LONG) .setAction("cancel", new View.OnClickListener() {@Overridepublic void onClick(View v) {//这里的单击事件代表点击消除Action后的响应事件} }) .show();} });} 效果如下: 2.2 AppBarLayout嵌套TabLayout 下面的例子用的是ViewPager,切记带有滚动属性的View需要设置app:layout_behavior属性。support library包含了一个特殊的字符串资源@string/appbar_scrolling_view_behavior,它和AppBarLayout.ScrollingViewBehavior相匹配,用来通知AppBarLayout 这个特殊的view何时发生了滚动事件,这个behavior需要设置在触发事件(滚动)的view之上。而AppBarLayout里面定义的view只要设置了app:layout_scrollFlags属性,就可以在滚动事件发生的时候被触发。同时注意:根据官方的谷歌文档,AppBarLayout目前必须是第一个嵌套在CoordinatorLayout里面的子view。 布局文件: <?xml version="1.0" encoding="utf-8"?><android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".activity.MainActivity"> <android.support.design.widget.AppBarLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:theme="@style/AppTheme.AppBarOverlay"> <android.support.v7.widget.Toolbarandroid:id="@+id/toolbar"android:layout_width="match_parent"android:layout_height="?attr/actionBarSize"android:background="?attr/colorPrimary"app:popupTheme="@style/AppTheme.PopupOverlay"app:layout_scrollFlags="scroll|enterAlways"/> <android.support.design.widget.TabLayoutandroid:id="@+id/tabs"android:layout_width="match_parent"android:layout_height="wrap_content" /> </android.support.design.widget.AppBarLayout> <android.support.v4.view.ViewPagerandroid:id="@+id/viewpager"android:layout_width="match_parent"android:layout_height="match_parent"app:layout_behavior="@string/appbar_scrolling_view_behavior" /> <android.support.design.widget.FloatingActionButtonandroid:id="@+id/fab"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="bottom|end"android:layout_margin="@dimen/fab_margin"android:src="@android:drawable/ic_dialog_email" /></android.support.design.widget.CoordinatorLayout> 具体代码就不再写了,想看的可以下载源码,效果如下: 2.3 AppBarLayout嵌套CollapsingToolbarLayout CollapsingToolbarLayout还能让我们做出更高级的动画,比如在里面放一个ImageView,然后在它折叠的时候渐渐淡出。同时在用户滚动的时候title的高度也会随着改变。 <?xml version="1.0" encoding="utf-8"?><android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".activity.MainActivity4"> <android.support.design.widget.AppBarLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:fitsSystemWindows="true"android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> <android.support.design.widget.CollapsingToolbarLayoutandroid:id="@+id/collapsing_toolbar"android:layout_width="match_parent"android:layout_height="match_parent"android:fitsSystemWindows="true"app:contentScrim="?attr/colorPrimary"app:expandedTitleMarginEnd="64dp"app:expandedTitleMarginStart="48dp"app:layout_scrollFlags="scroll|exitUntilCollapsed"> <ImageViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:fitsSystemWindows="true"android:scaleType="centerCrop"android:src="@mipmap/smile"app:layout_collapseMode="parallax" /> <android.support.v7.widget.Toolbarandroid:id="@+id/toolbar_main4"android:layout_width="match_parent"android:layout_height="?attr/actionBarSize"app:layout_scrollFlags="scroll|enterAlways"app:layout_collapseMode="pin"app:popupTheme="@style/ThemeOverlay.AppCompat.Light" /> </android.support.design.widget.CollapsingToolbarLayout> </android.support.design.widget.AppBarLayout> <android.support.v7.widget.RecyclerViewandroid:id="@+id/recycle_main4"android:layout_width="match_parent"android:layout_height="wrap_content"app:layout_behavior="@string/appbar_scrolling_view_behavior" /> <android.support.design.widget.FloatingActionButtonandroid:id="@+id/fab_main4"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="bottom|end"android:layout_margin="@dimen/fab_margin"android:src="@android:drawable/ic_dialog_email" /></android.support.design.widget.CoordinatorLayout> 现在效果就成了: + 为了制造出这种效果,我们添加一个定义了app:layout_collapseMode="parallax"属性的ImageView. 这种效果在详情页面用的较多,展示个性化内容,图像有强烈的吸引力。这个效果重点使用了CollapsingToolbarLayout 。 CollapsingToolbarLayout 提供以下属性和方法使用: 1. Collapsing title:ToolBar的标题,当CollapsingToolbarLayout全屏没有折叠时,title显示的是大字体,在折叠的过程中,title不断变小到一定大小的效果。通常,我们都是设置Toolbar的title,而现在,我们需要把title设置在CollapsingToolBarLayout上,而不是Toolbar。你可以调用setTitle(CharSequence)方法设置title。 2. Content scrim:ToolBar被折叠到顶部固定时候的背景,你可以调用setContentScrim(Drawable)方法改变背景或者 在属性中使用 app:contentScrim=”?attr/colorPrimary”来改变背景。 3. Status bar scrim:状态栏的背景,调用方法setStatusBarScrim(Drawable)。还没研究明白,不过这个只能在Android5.0以上系统有效果。 4. Parallax scrolling children:CollapsingToolbarLayout滑动时,子视图的视觉差,可以通过属性 app:layout_collapseParallaxMultiplier=”0.6”改变。值de的范围[0.0,1.0],值越大视察越大。 5. CollapseMode :子视图的折叠模式,在子视图设置,有两种“pin”:固定模式,在折叠的时候最后固定在顶端;“parallax”:视差模式,在折叠的时候会有个视差 折叠的效果。我们可以在布局中使用属性app:layout_collapseMode=”parallax”来改变。 三、自定义Behavior CoordinatorLayout功能之所以如此强大,就在于Behavior对象,这个Behavior用于当滚动发生的时候让AppBarLayout发生改变。CoordinatorLayout自己并不控制View, 所有的控制权都在Behavior。前面写到了 FloatingActionButton.Behavior,AppBarLayout.Behavior, AppBarLayout.ScrollingViewBehavior。 AppBarLayout中有两个Behavior,一个是拿来给它自己用的,另一个是拿来给它的兄弟结点用的。这些Behavior实现了复杂的控制功能。但系统的Behavior毕竟有限,我们可以通过自定义的方式来实现自己的Behavior。 通过 CoordinatorLayout.Behavior(YourView.Behavior.class) 来定义自己的Behavior,并在layout 文件中设置 app:layout_behavior=”com.example.app.YourView$Behavior” 来达到效果。 自定义Behavior 需要重写两个方法: publicbooleanlayoutDependsOn(CoordinatorLayout parent, View child, View dependency) publicbooleanonDependentViewChanged(CoordinatorLayout parent, View child, View dependency) 创建一个Behavior很简单,只要继承Behavior类即可 public class CustomBehavior<V extends View> extends CoordinatorLayout.Behavior<V> {public CustomBehavior(Context context, AttributeSet attrs) {super(context, attrs);}} 在上面这段代码中使用了范型,此时CustomBehavior可以被添加到任何View上,如果希望CustomBehavior只被添加到特定的View子类上,可以采用如下写法: publicclassCustomBehaviorextendsCoordinatorLayout.Behavior<FloatingActionButton> 另外在Behavior的使用中,可以使用Behavior.setTag()/Behavior.getTag()来保存临时性的变量,另外也可以使用onSaveInstanceState()/onRestoreInstanceState()进行数据保存。善用这些方法可以让Behavior更具状态性。 添加Behavior Behavior本身并不做任何事情,它们需要被添加到CoordinatorLayout的直接子类中才能被使用。主要有三种方法来将Behavior添加进子类,分别是程序中动态添加,Xml布局文件添加和使用注解添加。 1、程序中动态添加 CustomBehaviorcustomBehavior = new CustomBehavior (); CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) yourView.getLayoutParams();params.setBehavior(customBehavior); 在上面的这个例子中,我们在代码中添加了customBehavior,同时也是使用了CustomBehavior()这个构造函数,如果对CustomBehavior的构造过程需要额外的参数,可以自行重载构造函数。 2、Xml布局文件中添加 <FrameLayout android:layout_height=”wrap_content” android:layout_width=”match_parent” app:layout_behavior=”.CustomBehavior” /> 使用layout_behavior属性进行添加可以让代码更简洁些 ,属性内容是你的类名。需要注意的是使用这种方法,CustomBehavior(Context context, AttributeSet attrs)这个构造函数会被默认调用,这样我们就可以为其自定义一些xml属性,以保证其他开发者可以通过xml来修改CustomBehavior的行为。 3、使用注解添加如果你构建了一个自己的视图,并且这个视图需要一个自定义的Behavior,那么你就可以使用下面这种方式: @CoordinatorLayout.DefaultBehavior(CustomBehavior.class) publicclassMyFloatingActionButton extendsFloatingActionButton{ } 使用这种方式添加的Behavior被设置成了DefaultBehavior,如果这时在Xml中使用layout_behavior的话,这个DefaultBehavior会被覆盖。 因为个人能力有限,对CoordinatorLayout的介绍就这么多吧,希望各位大神能不吝赐教 源代码参考: http://blog.csdn.net/xyz_lmn/article/details/48055919 http://www.open-open.com/lib/view/open1453021356261.html http://www.w2bc.com/Article/49080 http://www.open-open.com/lib/view/open1437312265428.html http://www.w2bc.com/article/101849?from=extend

优秀的个人博客,低调大师

HBASE解析

Hbase是运行在Hadoop上的NoSQL数据库,它是一个分布式的和可扩展的大数据仓库,也就是说HBase能够利用HDFS的分布式处理模式,并从Hadoop的MapReduce程序模型中获益。这意味着在一组商业硬件上存储许多具有数十亿行和上百万列的大表。除去Hadoop的优势,HBase本身就是十分强大的数据库,它能够融合key/value存储模式带来实时查询的能力,以及通过MapReduce进行离线处理或者批处理的能力。总的来说,Hbase能够让你在大量的数据中查询记录,也可以从中获得综合分析报告。 谷歌曾经面对过一个挑战的问题:如何能在整个互联网上提供实时的搜索结果?答案是它本质上需要将互联网缓存,并重新定义在这样庞大的缓存上快速查找的新方法。为了达到这个目的,定义如下技术: 谷歌文件系统GFS:可扩展分布式文件系统,用于大型的、分布式的、数据密集型的应用程序。 BigTable:分布式存储系统,用于管理被设计成规模很大的结构化数据:来自数以千计商用服务器的PB级别的数据。 MapReduce:一个程序模型,用于处理和生成大数据集的相关实现。 在谷歌发布这些技术的文档之后, 不久以后我们就看到了它们的开源实现版本,就在2007年,Mike Cafarella发布了BigTable开源实现的代码,他称其为HBase,自此,HBase成为Apache的顶级项目,并运行在Facebook,Twitter,Adobe……仅举几个例子。 HBase不是一个关系型数据库,它需要不同的方法定义你的数据模型,HBase实际上定义了一个四维数据模型,下面就是每一维度的定义: 行键:每行都有唯一的行键,行键没有数据类型,它内部被认为是一个字节数组。 列簇:数据在行中被组织成列簇,每行有相同的列簇,但是在行之间,相同的列簇不需要有相同的列修饰符。在引擎中,HBase将列簇存储在它自己的数据文件中,所以,它们需要事先被定义,此外,改变列簇并不容易。 列修饰符:列簇定义真实的列,被称之为列修饰符,你可以认为列修饰符就是列本身。 版本:每列都可以有一个可配置的版本数量,你可以通过列修饰符的制定版本获取数据。 1.HBase Four-Dimensional Data Model 如图1中所示,通过行键获取一个指定的行,它由一个或多个列簇构成,每个列簇有一个或多个列修饰符(图1中称为列),每列又可以有一个或多个版本。为了获取指定数据,你需要知道它的行键、列簇、列修饰符以及版本。当设计HBase数据模型时,对考虑数据是如何被获取是十分有帮助的。你可以通过以下两种方式获得HBase数据: 通过他们的行键,或者一系列行键的表扫描。 使用map-reduce进行批操作 这种双重获取数据的方法使得HBase变得十分强大,典型地,在Hadoop中存储数据意味着它对离线或批处理方式分析是有益的(尤其是批处理分析),但是,对实时获取是不必要的。HBase通过key/value存储来支持实时分析,以及通过map-reduce支持批处理分析。让我们首先来看实时数据获取,作为key/value存储,key是行键,value是列簇的集合,如图2所示。 2.HBase as a Key/Value Store 如你在图2中看到的,key是我们所提到过的行键,value是列簇的集合。你可以通过key检索到value,或者换句话说,你可以通过行键“得到”行,或者你能通过给定起始和终止行键检索一系列行,这就是前面提到的表扫描。你不能实时的查询一个列的值,这就引出了一个重要的话题:行键的设计。 有两个原因令行键的设计十分重要: 表扫描是对行键的操作,所以,行键的设计控制着你能够通过HBase执行的实时/直接获取量。 当在生产环境中运行HBase时,它在HDFS上部运行,数据基于行键通过HDFS,如果你所有的行键都是以user-开头,那么很有可能你大部分数据都被分配一个节点上(违背了分布式数据的初衷),因此,你的行键应该是有足够的差异性以便分布式地通过整个部署。 你定义行键的方式取决于你想怎样存取那些行。如果你想以用户为基础存储数据,那么一个策略是利用字节队列在HBase中存储行键,所以我们可以创建一个用户ID的哈希(例如MD5或SHA-1),然后在哈希后面附上时间(long类型)。使用哈希有两个重点:(1)是它能够将value分散开,数据能够分布式地通过簇,(2)是它确保key的长度是一致的,以更加容易在表扫描中使用。 讲了足够多的理论,下面部分向你展示如何搭建HBase环境,并如何通过命令行使用。 你可以从Apache网站下载HBase,在写本文时,最新的版本是0.98.5,HBase团队推荐你在UNIX/Linux环境下安装HBase,如果你想在Windows下运行,你需要先安装Cygwin,并在这上运行HBase。当你下载完这些文件,解压到硬盘上。此外,你还需要安装Java环境,如果你还没有,从Oracle网站下载Java环境。在环境配置中添加名为HBASE_HOME的变量,值为你解压HBase文件的根目录,随后,执行bin文件夹下的start-hbase.sh脚本,它会在下面目录输出日志文件: $HBASE_HOME/logs/ 你可以在浏览器中输入下面URL测试是否安装正确: http://localhost:60010 如果安装正确,你应该看到下面界面。 转自:http://blog.jobbole.com/83614/

优秀的个人博客,低调大师

ReentrantLock源码解析

谈到多线程,就不避开锁(Lock),jdk中已经为我们提供了好几种锁的实现,已经足以满足我们大部分的需求了,今天我们就来看下最常用的ReentrantLock的实现。 其实最开始是想写一篇关于StampedLock的源码分析的,但发现写StampedLock前避不开ReentrantReadWriteLock,写ReentrantReadWriteLock又避不开ReentrantLock,他们仨是逐层递进的关系。ReentrantReadWriteLock解决了一些ReentrantLock无法解决的问题,StampedLock又弥补了ReentrantReadWriteLock的一些不足,三者有各自的设计和有缺点,这篇文章先和你一起看下ReentrantLock,之后我们会再一起去了解ReentrantReadWriteLock和StampedLock,相信有了ReentrantLock的基础后面的内容也会容易理解很多。 相对于jdk中很多其他的类来说,ReentrantLock提供的接口已经算是非常简单,事实上它只有一个构造参数boolean fair,用来指定是公平锁还是非公平锁,如果你指定的话默认是非公平锁。 public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); } 什么是公平?这里的的公平是指每个线程可以有公平的机会获取到这把锁,10个线程竞争这把锁,某个线程各有10%的机会获取到锁。听起来很理想主义,但大多数时候不建议使用公平锁,因为局部性的存在,每个线程对锁的真正需求度是不同的,有些线程就是需要很频繁的占有锁,有些偶尔占有就行。如果你单纯是为了公平而导致供需不平衡,可能有些线程会浪费锁的持有时间,而有些线程急需用锁但迟迟获取不到,导致线程饥饿,最终导致整个系统的性能不是最大化的。 最大化锁的使用率和代码性能就成了锁设计最重要的目标。试想如果我们提前知道每个线程对锁的需求度,然后按需求度给他们分配锁的占有机会,这样必然能达到锁的最优使用率。但实际上对于jdk的开发者来说,他哪知道你要拿锁去做啥、要开几个线程?所以ReentrantReadWriteLock的设计者用一种很简单粗暴的方式解决了大部分的问题,我们直接上源码。 ReentrantLock中最核心的就是Sync的实现,它默认已经实现了非公平锁的功能,所以你会看到NonfairSync只是简简单单继承了Sync而已。而Sync的主要功能还是继承了AbstractQueuedSynchronizer(AQS)。 AbstractQueuedSynchronizer 简单来说就是维护了一个状态 __state__,和一个等待线程队列(一个双向链表),然后通过VarHandle提供的CAS操作保证线程安全。当你在调用lock()的时候,会直接调用到AbstractQueuedSynchronizer中的acquire(int arg) public final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); } acquire也很简单,尝试去获取锁,如果获取失败,就把当前线程加到等待队列里(排队),并把当前线程的状态设置为可中断。 回到ReentrantLock,我们来开下它是如何依赖Sync来实现非公平锁的。NonfairSync在执行tryAcquire(int arg)的时候,实际执行的是以下代码。 final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { //如果state是0,说明当前没有线程持有锁,用CAS更新状态,如果CAS成功,就在锁中写入当前线程的信息。 if (compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } else if (current == getExclusiveOwnerThread()) { //如果state不是0,也不一定获取锁失败,要看下持有锁的线程是不是自己,如果是更新state int nextc = c + acquires; if (nextc < 0) // overflow throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; } 从这可以看出来ReentrantLock是可重入锁,state的目的就是为了记录当前锁被同一个线程获取了几次。但是看完这段代码你肯定没看出来哪 __不公平了__。别急,我们来对比下公平锁的实现就知道了。 static final class FairSync extends Sync { private static final long serialVersionUID = -3000897897090466540L; @ReservedStackAccess protected final boolean tryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { if (!hasQueuedPredecessors() && // 不同之处 compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; } } FairSync也是继承自Sync,但它重写了加锁tryAcquire方法,打眼一看和上面非公平锁的tryAcquire非常像,唯一不同之处就是在state为0时多了个!hasQueuedPredecessors()的判断。hasQueuedPredecessors()方法是判断是否有线程在等待去获取这把锁,如果有其他线程这次就算是获取锁失败了。 来个易懂的例子,现在办公室只有一间卫生间,很多个同事共用,有人在用卫生间的时候也不会希望别人跑进来和他一起用。公平锁的实现方式就是我来上卫生间,发现卫生间没人用,但有人在排队等卫生间(可能是玩手机没注意卫生间空了),我只能乖乖排队。非公平锁的实现方式是,我来上卫生间,发现卫生间是空的,不管有没有人排队我都占了,这样显然对其他排队的人来说是不公平的。 这种方式在现实世界看起来是非常不合理的,但是如果换种视角,可能越着急的人才是越需要用卫生间的人(可能他拉肚子),让排队的人多等会无所谓,这样才能最大化卫生间的的价值。虽然拉肚子在现实世界不常见,在在计算机中以纳秒计的世界里,有些线程就是比其他线程急很多的情况非常常见,非公平的方式就很合情。再从概率的角度看,如果有个线程需要以更高的频次使用这把锁,不排队去获取锁能舍得锁被获取到的次数最大化,也很合理。所以非公平锁合情合理。但历史告诉我们,凡事没有绝对,还是需要具体问题具体分析,有些情况下,非公平锁会导致线程饥饿。 public void unlock() { sync.release(1); } public final boolean release(int arg) { if (tryRelease(arg)) { Node h = head; if (h != null && h.waitStatus != 0) unparkSuccessor(h); return true; } return false; } unlock()调用了sync中的release(),release()是继承自AQS,跳到AQS中就会发现又调用了tryRelease()。ReentrantLock重写了tryRelease(),源码如下,也比较简单。 protected final boolean tryRelease(int releases) { int c = getState() - releases; if (Thread.currentThread() != getExclusiveOwnerThread()) throw new IllegalMonitorStateException(); boolean free = false; if (c == 0) { free = true; setExclusiveOwnerThread(null); } setState(c); return free; } 释放锁的过程是先判断是否是锁持有线程,然后更新锁状态。如果你进到setExclusiveOwnerThread(null)和setState(c)里面,就会发现这里没有用到CAS,会不会出现线程安全的问题?仔细想想其实不会有线程安全的问题, if (Thread.currentThread() != getExclusiveOwnerThread())判断了是当前线程是否持有锁,保证后续逻辑只有持有锁的线程才会执行到,因为之前获取锁是用CAS保证线程安全的,所以后面的逻辑也一定是线程安全的。 除了加锁和释放锁外,ReentrantLock还提供了和锁、线程相关的的接口,如上图,从函数名就可以看出其作用了,而且实现代码比较简单,这里就不再赘述了,有兴趣可以自行查看源码。

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册