代码拉取完成,页面将自动刷新
<!DOCTYPE html>
<html class="theme-next mist use-motion" lang="zh-Hans">
<head>
<meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
<meta name="theme-color" content="#222">
<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
<link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css" />
<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css" />
<link href="/css/main.css?v=5.1.2" rel="stylesheet" type="text/css" />
<meta name="keywords" content="Hexo, NexT" />
<link rel="alternate" href="/atom.xml" title="学不可以已" type="application/atom+xml" />
<link rel="shortcut icon" type="image/x-icon" href="/uploads/favicon.ico?v=5.1.2" />
<meta name="description" content="青,取之于蓝,而青于蓝">
<meta property="og:type" content="website">
<meta property="og:title" content="学不可以已">
<meta property="og:url" content="http://eregg.com/index.html">
<meta property="og:site_name" content="学不可以已">
<meta property="og:description" content="青,取之于蓝,而青于蓝">
<meta property="og:locale" content="zh-Hans">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="学不可以已">
<meta name="twitter:description" content="青,取之于蓝,而青于蓝">
<script type="text/javascript" id="hexo.configurations">
var NexT = window.NexT || {};
var CONFIG = {
root: '/',
scheme: 'Mist',
version: '5.1.2',
sidebar: {"position":"left","display":"post","offset":12,"offset_float":12,"b2t":false,"scrollpercent":false,"onmobile":false},
fancybox: true,
tabs: true,
motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn"}},
duoshuo: {
userId: '0',
author: '博主'
},
algolia: {
applicationID: '',
apiKey: '',
indexName: '',
hits: {"per_page":10},
labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
}
};
</script>
<link rel="canonical" href="http://eregg.com/"/>
<title>学不可以已</title>
<script type="text/javascript">
var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?5f1629a8f7280df347a90a49b56b2b49";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script>
</head>
<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">
<div class="container sidebar-position-left
page-home">
<div class="headband"></div>
<header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
<div class="header-inner"><div class="site-brand-wrapper">
<div class="site-meta ">
<div class="custom-logo-site-title">
<a href="/" class="brand" rel="start">
<span class="logo-line-before"><i></i></span>
<span class="site-title">学不可以已</span>
<span class="logo-line-after"><i></i></span>
</a>
</div>
<p class="site-subtitle">青,取之于蓝,而青于蓝</p>
</div>
<div class="site-nav-toggle">
<button>
<span class="btn-bar"></span>
<span class="btn-bar"></span>
<span class="btn-bar"></span>
</button>
</div>
</div>
<nav class="site-nav">
<ul id="menu" class="menu">
<li class="menu-item menu-item-home">
<a href="/" rel="section">
<i class="menu-item-icon fa fa-fw fa-home"></i> <br />
首页
</a>
</li>
<li class="menu-item menu-item-tags">
<a href="/tags/" rel="section">
<i class="menu-item-icon fa fa-fw fa-tags"></i> <br />
标签
</a>
</li>
<li class="menu-item menu-item-archives">
<a href="/archives/" rel="section">
<i class="menu-item-icon fa fa-fw fa-archive"></i> <br />
归档
</a>
</li>
</ul>
</nav>
</div>
</header>
<main id="main" class="main">
<div class="main-inner">
<div class="content-wrap">
<div id="content" class="content">
<section id="posts" class="posts-expand">
<article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
<div class="post-block">
<link itemprop="mainEntityOfPage" href="http://eregg.com/2016/11/22/Lucene核心API/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="name" content="eregg">
<meta itemprop="description" content="">
<meta itemprop="image" content="/uploads/avatar.jpg">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="学不可以已">
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2016/11/22/Lucene核心API/" itemprop="url">Lucene核心API</a></h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建于" itemprop="dateCreated datePublished" datetime="2016-11-22T09:41:08+08:00">
2016-11-22
</time>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h4 id="LUCENE是什么"><a href="#LUCENE是什么" class="headerlink" title="LUCENE是什么"></a><a href="#LUCENE是什么" title="LUCENE是什么"></a>LUCENE是什么</h4><blockquote>
<p><strong>Lucene是一款高性能的,可扩展的信息检索(IR)工具库</strong>,信息检索是指文档搜索,文档内信息搜索或者文档相关元数据搜索操作等,Lucene能够融入到你的应用程序当中,以增加搜索功能。它是一款以java实现的成熟,自由,开源的软件项目,也是apache软件基金中的一个项目,并且基于apache软件许可协议授权。因此,lucene在近年来已经成为最受欢迎的开源信息检索工具库。</p>
<p>Lucene是一个快速发展的项目。</p>
</blockquote>
<h4 id="Lucene-和搜索程序组建"><a href="#Lucene-和搜索程序组建" class="headerlink" title="Lucene 和搜索程序组建"></a><a href="#Lucene-和搜索程序组建" title="Lucene 和搜索程序组建"></a>Lucene 和搜索程序组建</h4><blockquote>
<p><strong>检索原始内容;将原始内容,封装到Field对象,在将Field对象添加到Docuemnt对象,然后将Document对象写入索引库,一旦建立索引,用于搜索的组建也就出来了,这些搜索的组建包括:用户接口,构建可编程查询语句的方法,执行查询语句,展现查询结果等</strong>。</p>
</blockquote>
<h4 id="索引过程的核心类"><a href="#索引过程的核心类" class="headerlink" title="索引过程的核心类"></a><a href="#索引过程的核心类" title="索引过程的核心类"></a>索引过程的核心类</h4><figure class="highlight xl"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">graph LR</div><div class="line"><span class="function"><span class="title">filed</span>–></span>Document</div><div class="line"><span class="function"><span class="title">filed</span>–></span>Document</div><div class="line"><span class="function"><span class="title">filed</span>–></span>Document</div><div class="line">D<span class="function"><span class="title">ocument</span>–></span>Analyzer</div><div class="line">A<span class="function"><span class="title">nalyzer</span>–></span>indexWriter</div><div class="line"><span class="function"><span class="title">indexWriter</span>–></span>Directory</div></pre></td></tr></table></figure>
<h5 id="IndexWriter"><a href="#IndexWriter" class="headerlink" title="IndexWriter"></a><a href="#IndexWriter" title="IndexWriter"></a>IndexWriter</h5><blockquote>
<p><strong>IndexWriter(写索引)是索引过程的核心组建。这个类负责创建新索引或者打开已有的索引,以及向索引中添加,删除或者更新被索引的文档信息</strong>。可以把IndexWriter看做这样一个对象:它为你提供针对索引文件的写入操作,但不能用于读取或搜索索引。IndexWriter需要开辟一定的空间来存储索引,该功能可以由Directory完成。</p>
</blockquote>
<h5 id="Directory"><a href="#Directory" class="headerlink" title="Directory"></a><a href="#Directory" title="Directory"></a>Directory</h5><blockquote>
<p><strong>Directory 类描述了Lucene索引的存放位置</strong>。它是一个抽象类,它的子类负责具体指定索引的存储路径。可以存放在磁盘上(FSDirectory),也可以存放在内存中(RAMDirectory)等待。。</p>
</blockquote>
<h5 id="Analyzer"><a href="#Analyzer" class="headerlink" title="Analyzer"></a><a href="#Analyzer" title="Analyzer"></a>Analyzer</h5><blockquote>
<p>文本文件在被索引之前,需要经过Analyzer(分词器)处理。<strong>它负责从被索引文本文件中提取语汇单元,并剔除剩下的无用信息</strong>。分词器主要分析的对象是Document对象,该文档对象包含了一些分离的能被索引的域。</p>
</blockquote>
<h5 id="Document"><a href="#Document" class="headerlink" title="Document"></a><a href="#Document" title="Document"></a>Document</h5><blockquote>
<p><strong>Document(文档)对象代表一些域(Field)的集合</strong>。可以将Document对象理解为虚拟文档——比如web页面,Email信息或者文本文件————然后从中取回大量元数据(如:作者,标题,摘要,URL……),这作为文档的不同域单独存储并被索引。</p>
</blockquote>
<h5 id="Field"><a href="#Field" class="headerlink" title="Field"></a><a href="#Field" title="Field"></a>Field</h5><blockquote>
<p><strong>索引中的每个文档都包含一个或多个不同命名的域,这些域包含在Field类中。每个域都有一个域名和对应的域值,以及一组选项来精准控制Lucene索引操作的各个域值</strong>。</p>
<table><br><thead><br><tr><br><th>Field类</th><br><th>数据类型</th><br><th>Analyzed是否分析</th><br><th>Indexed是否索引</th><br><th>Stored是否存储</th><br><th>说明</th><br></tr><br></thead><br><tbody><br><tr><br><td>StringField(FieldName, FieldValue,Store.YES))</td><br><td>字符串</td><br><td>N</td><br><td>Y</td><br><td>Y or N</td><br><td>这个Field用来构建一个字符串Field,但是不会进行分析,会将整个串存储在索引中,比如(订单号,姓名等)是否存储在文档中用Store.YES或Store.NO决定</td><br></tr><br><tr><br><td>LongField(FieldName, FieldValue,Store.YES)</td><br><td>Long型</td><br><td>Y</td><br><td>Y</td><br><td>Y or N</td><br><td>这个Field用来构建一个Long数字型Field,进行分析和索引,比如(价格)是否存储在文档中用Store.YES或Store.NO决定</td><br></tr><br><tr><br><td>StoredField(FieldName, FieldValue)</td><br><td>重载方法,支持多种类型</td><br><td>N</td><br><td>N</td><br><td>Y</td><br><td>这个Field用来构建不同类型Field不分析,不索引,但要Field存储在文档中。</td><br></tr><br><tr><br><td>TextField(FieldName, FieldValue, Store.NO)或TextField(FieldName, reader)</td><br><td>字符串或流</td><br><td>Y</td><br><td>Y</td><br><td>Y or N</td><br><td>如果是一个Reader,lucene猜测内容比较多,会采用Unstored的策略</td><br></tr><br></tbody><br></table>
</blockquote>
<h4 id="搜索过程的核心类"><a href="#搜索过程的核心类" class="headerlink" title="搜索过程的核心类"></a><a href="#搜索过程的核心类" title="搜索过程的核心类"></a>搜索过程的核心类</h4><h5 id="IndexSearcher"><a href="#IndexSearcher" class="headerlink" title="IndexSearcher"></a><a href="#IndexSearcher" title="IndexSearcher"></a>IndexSearcher</h5><blockquote>
<p><strong>IndexSearcher 类用于搜素由IndexWriter类创建的索引</strong>:这个类公开几个搜索方法,它是连接索引的中心环节。可以将IndexSearcher类看做一个以只读方式打开索引的类。它需要利用Directory实例来掌控前期创建的索引,然后才能提供大量的搜索方法。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//该对象的典型应用如下</span></div><div class="line">IndexReader reader = DirectoryReader.open(FSDirectory.open(<span class="keyword">new</span> File(<span class="string">“/tmp/lucene/indexdata”</span>)));</div><div class="line"></div><div class="line">IndexSearcher searcher = <span class="keyword">new</span> IndexSearcher(reader);</div><div class="line"></div><div class="line">Query query = <span class="keyword">new</span> TermQuery(<span class="keyword">new</span> Term(<span class="string">“filename”</span>, <span class="string">“检索”</span>));</div><div class="line">TopDocs docs = searcher.search(query, <span class="number">10</span>);</div></pre></td></tr></table></figure>
</blockquote>
<h5 id="Term"><a href="#Term" class="headerlink" title="Term"></a><a href="#Term" title="Term"></a>Term</h5><blockquote>
<p><strong>Term对象是搜索功能的基本单元。与Field对象类似,Term对象包含一对字符串元素:域名和单词(或域文本值)。</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//在搜索过程中可以创建Term对象,并和QueryTerm对象一起使用</span></div><div class="line">Query query = <span class="keyword">new</span> TermQuery(<span class="keyword">new</span> Term(<span class="string">“filename”</span>, <span class="string">“检索”</span>));</div><div class="line">TopDocs docs = searcher.search(query, <span class="number">10</span>);</div></pre></td></tr></table></figure>
</blockquote>
<h5 id="Query"><a href="#Query" class="headerlink" title="Query"></a><a href="#Query" title="Query"></a>Query</h5><blockquote>
<p>Lucene含有许多具体的Query(查询)子类。</p>
</blockquote>
<h6 id="TermQuery-通过项进行搜索"><a href="#TermQuery-通过项进行搜索" class="headerlink" title="TermQuery 通过项进行搜索"></a><a href="#TermQuery-通过项进行搜索" title="TermQuery 通过项进行搜索"></a>TermQuery 通过项进行搜索</h6><blockquote>
<p><strong>TremQuery 是Lucene提供的最基本的查询类型,也是最简单的查询类型之一。它用来匹配指定域中包含特定值的文档</strong>。</p>
</blockquote>
<h6 id="TermRangeQuery-在指定的项范围内搜索"><a href="#TermRangeQuery-在指定的项范围内搜索" class="headerlink" title="TermRangeQuery 在指定的项范围内搜索"></a><a href="#TermRangeQuery-在指定的项范围内搜索" title="TermRangeQuery 在指定的项范围内搜索"></a>TermRangeQuery 在指定的项范围内搜索</h6><blockquote>
<p>索引中的各个Term对象会按照字典排序顺序进行排序,并允许在Lucene的TermRangeQuery对象提供的范围内进行文本项的直接搜索。</p>
</blockquote>
<h6 id="NumericRangeQuery-在指定的数字范围内搜索"><a href="#NumericRangeQuery-在指定的数字范围内搜索" class="headerlink" title="NumericRangeQuery 在指定的数字范围内搜索"></a><a href="#NumericRangeQuery-在指定的数字范围内搜索" title="NumericRangeQuery 在指定的数字范围内搜索"></a>NumericRangeQuery 在指定的数字范围内搜索</h6><blockquote>
<p>如果使用NumericField对象来索引域,那么就能使用NumericRangeQuery类在某个特定范围内搜索该域。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//数字范围查询</span></div><div class="line">Query query = NumericRangeQuery.newLongRange(<span class="string">“fileSize”</span>, <span class="number">0l</span>, <span class="number">1000l</span>, <span class="keyword">true</span>, <span class="keyword">true</span>);</div><div class="line"></div><div class="line"><span class="keyword">this</span>.search(booleanQuery);</div><div class="line">查询条件:fileSize:[<span class="number">0</span> TO <span class="number">1000</span>]</div></pre></td></tr></table></figure>
</blockquote>
<h6 id="PrefixQuery-通过字符串搜索"><a href="#PrefixQuery-通过字符串搜索" class="headerlink" title="PrefixQuery 通过字符串搜索"></a><a href="#PrefixQuery-通过字符串搜索" title="PrefixQuery 通过字符串搜索"></a>PrefixQuery 通过字符串搜索</h6><h6 id="FuzzyQuery-搜索类似项"><a href="#FuzzyQuery-搜索类似项" class="headerlink" title="FuzzyQuery 搜索类似项"></a><a href="#FuzzyQuery-搜索类似项" title="FuzzyQuery 搜索类似项"></a>FuzzyQuery 搜索类似项</h6><h6 id="MatchAllDocsQuery-匹配所有文档"><a href="#MatchAllDocsQuery-匹配所有文档" class="headerlink" title="MatchAllDocsQuery 匹配所有文档"></a><a href="#MatchAllDocsQuery-匹配所有文档" title="MatchAllDocsQuery 匹配所有文档"></a>MatchAllDocsQuery 匹配所有文档</h6><h6 id="WildcardQuery-通配符查询"><a href="#WildcardQuery-通配符查询" class="headerlink" title="WildcardQuery 通配符查询"></a><a href="#WildcardQuery-通配符查询" title="WildcardQuery 通配符查询"></a>WildcardQuery 通配符查询</h6><h6 id="BooleanQuery-组合查询"><a href="#BooleanQuery-组合查询" class="headerlink" title="BooleanQuery 组合查询"></a><a href="#BooleanQuery-组合查询" title="BooleanQuery 组合查询"></a>BooleanQuery 组合查询</h6><blockquote>
<p><strong>通过使用BooleanQuery类可以将所有Query子类,组合成复杂的查询方式</strong>,可以通过Occur来表示子句的逻辑“与”,逻辑“或” 或者逻辑“非”。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//组合查询(多条件组合查询)</span></div><div class="line">TermQuery query1 = <span class="keyword">new</span> TermQuery(<span class="keyword">new</span> Term(<span class="string">“filename”</span>, <span class="string">“apache”</span>));</div><div class="line">NumericRangeQuery<Long> query2 = NumericRangeQuery.newLongRange(<span class="string">“fileSize”</span>, <span class="number">0l</span>, <span class="number">1000l</span>, <span class="keyword">true</span>, <span class="keyword">true</span>);</div><div class="line">BooleanQuery booleanQuery = <span class="keyword">new</span> BooleanQuery();</div><div class="line"><span class="comment">//Occur.MUST:必须满足,Occur.MUST_NOT:必须不满足, Occur.SHOULD:或者的关系</span></div><div class="line">booleanQuery.add(query1, Occur.MUST);</div><div class="line">booleanQuery.add(query2, Occur.MUST);</div><div class="line"></div><div class="line"><span class="keyword">this</span>.search(booleanQuery);</div><div class="line">查询条件:+filename:apache +fileSize:[<span class="number">0</span> TO <span class="number">1000</span>]</div></pre></td></tr></table></figure>
</blockquote>
<h5 id="QueryParser-解析查询表达式"><a href="#QueryParser-解析查询表达式" class="headerlink" title="QueryParser 解析查询表达式"></a><a href="#QueryParser-解析查询表达式" title="QueryParser 解析查询表达式"></a>QueryParser 解析查询表达式</h5><blockquote>
<p>尽管基于API创建的查询对象很强大,但是如果所有的查询对象都必须通过java代码显式构造的话,这也是不合理的。通过使用自然语言表示的查询表达式,Lucene的QueryParser类可以创建前面介绍过的某一个Query子类。</p>
<p><strong>QueryParser 能够很好地为搜索用户提供形式自由的查询。为了完成这个任务,QueryParser 使用分词器将文本信息分割成各个项以用于搜索</strong>。在实例化QueryParser对象时,通用需要传入一个分词器对象。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="comment">/<em>*</em></span></div><div class="line"> 参数一:默认搜索域,参数二:分词器</div><div class="line"> */</div><div class="line">QueryParser queryParser = <span class="keyword">new</span> QueryParser(<span class="string">“filename”</span>, <span class="keyword">new</span> IKAnalyzer());</div><div class="line"><span class="comment">//parse 中可以不指定域,默认使用创建QueryParser时,指定的默认域(filename))</span></div><div class="line">Query query = queryParser.parse(<span class="string">“fileContent:全文检索”</span>);</div><div class="line"></div><div class="line"><span class="keyword">this</span>.search(query);</div><div class="line">查询条件:fileContent:全文 fileContent:检索</div></pre></td></tr></table></figure>
</blockquote>
<h6 id="MultiFieldQueryParser-一次性搜索多个域"><a href="#MultiFieldQueryParser-一次性搜索多个域" class="headerlink" title="MultiFieldQueryParser 一次性搜索多个域"></a><a href="#MultiFieldQueryParser-一次性搜索多个域" title="MultiFieldQueryParser 一次性搜索多个域"></a>MultiFieldQueryParser 一次性搜索多个域</h6><blockquote>
<p><strong>MultiFieldQueryParser 是QueryParser的子类</strong>。它会在后台程序中实例化一个QueryParser对象,用来针对每个域进行查询表达式的解析,然后使用BooleanQuery将查询组合起来。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//多个默认域,查询解析器</span></div><div class="line">String [] fields = {<span class="string">“filename”</span>, <span class="string">“fileContent”</span>};</div><div class="line"><span class="comment">//参数一:默认搜索域数组(可以指定多个默认搜索域) 参数2:解析查询短语的分词器</span></div><div class="line">MultiFieldQueryParser multiFieldQueryParser = <span class="keyword">new</span> MultiFieldQueryParser(fields, <span class="keyword">new</span> IKAnalyzer());</div><div class="line">Query query = multiFieldQueryParser.parse(<span class="string">“lucene is good”</span>);</div><div class="line"></div><div class="line"><span class="keyword">this</span>.search(query);</div><div class="line">查询条件:(filename:lucene fileContent:lucene) (filename:good fileContent:good)</div></pre></td></tr></table></figure><br><figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//多个默认域,查询解析器,设置域的权重,从而影响排序结果 </span></div><div class="line">String [] fields = {<span class="string">“filename”</span>, <span class="string">“fileContent”</span>};</div><div class="line">Map<String, Float> boosts = <span class="keyword">new</span> HashMap<String, Float>();</div><div class="line">boosts.put(<span class="string">“filename”</span>, <span class="number">1f</span>);</div><div class="line">boosts.put(<span class="string">“fileContent”</span>, <span class="number">10f</span>);</div><div class="line"><span class="comment">//参数一:默认搜索域数组(可以指定多个默认搜索域) 参数2:解析查询短语的分词器,参数3:设置域的权重值</span></div><div class="line">MultiFieldQueryParser multiFieldQueryParser = <span class="keyword">new</span> MultiFieldQueryParser(fields, <span class="keyword">new</span> IKAnalyzer(), boosts);</div><div class="line">Query query = multiFieldQueryParser.parse(<span class="string">“lucene is good”</span>);</div><div class="line"></div><div class="line"><span class="keyword">this</span>.search(query);</div><div class="line">查询条件:(filename:lucene fileContent:lucene^<span class="number">10.0</span>) (filename:good fileContent:good^<span class="number">10.0</span>)</div></pre></td></tr></table></figure>
</blockquote>
<h5 id="TopDocs"><a href="#TopDocs" class="headerlink" title="TopDocs"></a><a href="#TopDocs" title="TopDocs"></a>TopDocs</h5><blockquote>
<p><strong>TopDocs 类是一个简单的指针容器,指针一般指向前N个排名的搜索结果</strong>,搜索结果即匹配查询条件的文档。</p>
</blockquote>
<h4 id="实例一(建立索引)"><a href="#实例一(建立索引)" class="headerlink" title="实例一(建立索引)"></a><a href="#实例一(建立索引)" title="实例一(建立索引)"></a>实例一(建立索引)</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">package</span> com.eregg.lucene.demo;</div><div class="line"></div><div class="line"><span class="keyword">import</span> java.io.File;</div><div class="line"></div><div class="line"><span class="keyword">import</span> org.apache.commons.io.FileUtils;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.analysis.Analyzer;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.analysis.standard.StandardAnalyzer;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.document.Document;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.document.Field;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.document.Field.Store;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.document.LongField;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.document.StoredField;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.document.TextField;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.index.IndexWriter;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.index.IndexWriterConfig;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.store.Directory;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.store.FSDirectory;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.util.Version;</div><div class="line"><span class="keyword">import</span> org.junit.Test;</div><div class="line"><span class="keyword">import</span> org.wltea.analyzer.lucene.IKAnalyzer;</div><div class="line"></div><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">IndexBuilderDemo</span> </span>{</div><div class="line"></div><div class="line"> <span class="meta">@Test</span></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testBuilderIndex</span><span class="params">()</span> <span class="keyword">throws</span> Exception</span>{</div><div class="line"> </div><div class="line"> <span class="comment">//指定索引数据存放位置,可以存放在磁盘上,也可以存放在内存中</span></div><div class="line"> Directory directory = FSDirectory.open(<span class="keyword">new</span> File(<span class="string">“/tmp/lucene/indexdata”</span>));</div><div class="line"> </div><div class="line"> <span class="comment">//创建一个标准分词器</span></div><div class="line"> Analyzer analyzer = <span class="keyword">new</span> StandardAnalyzer();</div><div class="line"> analyzer = <span class="keyword">new</span> IKAnalyzer();</div><div class="line"> <span class="comment">//将分词器及版本分装到IndexWriter所需的参数对象中</span></div><div class="line"> IndexWriterConfig conf = <span class="keyword">new</span> IndexWriterConfig(Version.LUCENE_4_10_3, analyzer);</div><div class="line"> </div><div class="line"> <span class="comment">//根据索引库存放的目录,及需要的参数(版本,分词器)创建一个创建索引的工具indexWriter</span></div><div class="line"> IndexWriter indexWriter = <span class="keyword">new</span> IndexWriter(directory, conf);</div><div class="line"> indexWriter.deleteAll();<span class="comment">//删除原来的数据</span></div><div class="line"> </div><div class="line"> <span class="comment">/<em>*</em></span></div><div class="line"> 从原始数据中提取信息到document,然后用indexWriter写入到索引库(索引库,信息库)</div><div class="line"> */</div><div class="line"> File path = <span class="keyword">new</span> File(<span class="string">“/tmp/lucene/searchsource”</span>);</div><div class="line"> File [] files = path.listFiles();</div><div class="line"> String filename = <span class="keyword">null</span>;</div><div class="line"> String filePath = <span class="keyword">null</span>;</div><div class="line"> String fileContent = <span class="keyword">null</span>;</div><div class="line"> <span class="keyword">long</span> fileSize = <span class="number">0</span>;</div><div class="line"> </div><div class="line"> <span class="keyword">for</span> (File file : files) {</div><div class="line"> <span class="comment">//1.从原始数据提取出来的信息</span></div><div class="line"> filename = file.getName();</div><div class="line"> filePath = file.getPath();</div><div class="line"> fileContent = FileUtils.readFileToString(file);</div><div class="line"> fileSize = FileUtils.sizeOf(file);</div><div class="line"> </div><div class="line"> <span class="comment">//2.将提取出来的信息封装到field对象中</span></div><div class="line"> Field filenameField = <span class="keyword">new</span> TextField(<span class="string">“filename”</span>, filename, Store.YES);</div><div class="line"> Field filePathField = <span class="keyword">new</span> StoredField(<span class="string">“filePath”</span>, filePath);</div><div class="line"> Field fileContentField = <span class="keyword">new</span> TextField(<span class="string">“fileContent”</span>, fileContent, Store.NO);</div><div class="line"> LongField fileSizeField = <span class="keyword">new</span> LongField(<span class="string">“fileSize”</span>, fileSize, Store.YES);</div><div class="line"> </div><div class="line"> Document doc = <span class="keyword">new</span> Document();</div><div class="line"> doc.add(filenameField);</div><div class="line"> doc.add(filePathField);</div><div class="line"> doc.add(fileContentField);</div><div class="line"> doc.add(fileSizeField);</div><div class="line"> </div><div class="line"> indexWriter.addDocument(doc);</div><div class="line"> </div><div class="line"> System.out.println(<span class="string">“filename:”</span>+filename+<span class="string">“,fileSize:”</span>+fileSize);</div><div class="line"> }</div><div class="line"> </div><div class="line"> indexWriter.commit();</div><div class="line"> indexWriter.close();</div><div class="line"> </div><div class="line"> </div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<h4 id="实例二(搜索索引)"><a href="#实例二(搜索索引)" class="headerlink" title="实例二(搜索索引)"></a><a href="#实例二(搜索索引)" title="实例二(搜索索引)"></a>实例二(搜索索引)</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">package</span> com.eregg.lucene.demo;</div><div class="line"></div><div class="line"><span class="keyword">import</span> java.io.File;</div><div class="line"></div><div class="line"><span class="keyword">import</span> org.apache.lucene.document.Document;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.index.DirectoryReader;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.index.IndexReader;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.index.Term;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.search.IndexSearcher;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.search.Query;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.search.ScoreDoc;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.search.TermQuery;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.search.TopDocs;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.store.FSDirectory;</div><div class="line"><span class="keyword">import</span> org.junit.Test;</div><div class="line"></div><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">IndexSearchDemo</span> </span>{</div><div class="line"></div><div class="line"> <span class="meta">@Test</span></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testSearch</span><span class="params">()</span> <span class="keyword">throws</span> Exception</span>{</div><div class="line"> </div><div class="line"> <span class="comment">//通过Directory指定索引库所在位置</span></div><div class="line"> IndexReader reader = DirectoryReader.open(FSDirectory.open(<span class="keyword">new</span> File(<span class="string">“/tmp/lucene/indexdata”</span>)));</div><div class="line"> </div><div class="line"> <span class="comment">//创建一个查询对象</span></div><div class="line"> IndexSearcher searcher = <span class="keyword">new</span> IndexSearcher(reader);</div><div class="line"> </div><div class="line"> <span class="comment">//创建一个简单查询对象,通过指定域和特定值查询文档</span></div><div class="line"> Query query = <span class="keyword">new</span> TermQuery(<span class="keyword">new</span> Term(<span class="string">“filename”</span>, <span class="string">“检索”</span>));</div><div class="line"> <span class="comment">//TopDocs 类是一个简单的指针容器,指针一般指向前N个排名的搜索结果</span></div><div class="line"> TopDocs docs = searcher.search(query, <span class="number">10</span>);</div><div class="line"> <span class="keyword">int</span> total = docs.totalHits;</div><div class="line"> ScoreDoc [] scoreDocs = docs.scoreDocs;</div><div class="line"> System.out.println(<span class="string">“搜索得到的文档数:”</span>+total);</div><div class="line"> <span class="keyword">for</span> (ScoreDoc scoreDoc : scoreDocs) {</div><div class="line"> </div><div class="line"> Document doc = searcher.doc(scoreDoc.doc);</div><div class="line"> display(doc);</div><div class="line"> </div><div class="line"> }</div><div class="line"> }</div><div class="line"> </div><div class="line"> <span class="comment">/<strong></strong></span></div><div class="line"> <em> 打印输出文档</em></div><div class="line"> <span class="doctag">@param</span> doc</div><div class="line"> <em>/</em></div><div class="line"> <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">display</span><span class="params">(Document doc)</span></span>{</div><div class="line"> String filename = doc.get(<span class="string">“filename”</span>);</div><div class="line"> String filePath = doc.get(<span class="string">“filePath”</span>);</div><div class="line"> Long fileSize = <span class="keyword">new</span> Long(doc.get(<span class="string">“fileSize”</span>));</div><div class="line"> </div><div class="line"> System.out.println(<span class="string">“filename:”</span>+filename);</div><div class="line"> System.out.println(<span class="string">“filePath:”</span>+filePath);</div><div class="line"> System.out.println(<span class="string">“fileSize:”</span>+fileSize);</div><div class="line"> System.out.println(<span class="string">“<strong><strong><strong><strong><strong>**</strong></strong></strong></strong></strong>“</span>);</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<h4 id="实例三(Query的子类查询)"><a href="#实例三(Query的子类查询)" class="headerlink" title="实例三(Query的子类查询)"></a><a href="#实例三(Query的子类查询)" title="实例三(Query的子类查询)"></a>实例三(Query的子类查询)</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div><div class="line">82</div><div class="line">83</div><div class="line">84</div><div class="line">85</div><div class="line">86</div><div class="line">87</div><div class="line">88</div><div class="line">89</div><div class="line">90</div><div class="line">91</div><div class="line">92</div><div class="line">93</div><div class="line">94</div><div class="line">95</div><div class="line">96</div><div class="line">97</div><div class="line">98</div><div class="line">99</div><div class="line">100</div><div class="line">101</div><div class="line">102</div><div class="line">103</div><div class="line">104</div><div class="line">105</div><div class="line">106</div><div class="line">107</div><div class="line">108</div><div class="line">109</div><div class="line">110</div><div class="line">111</div><div class="line">112</div><div class="line">113</div><div class="line">114</div><div class="line">115</div><div class="line">116</div><div class="line">117</div><div class="line">118</div><div class="line">119</div><div class="line">120</div><div class="line">121</div><div class="line">122</div><div class="line">123</div><div class="line">124</div><div class="line">125</div><div class="line">126</div><div class="line">127</div><div class="line">128</div><div class="line">129</div><div class="line">130</div><div class="line">131</div><div class="line">132</div><div class="line">133</div><div class="line">134</div><div class="line">135</div><div class="line">136</div><div class="line">137</div><div class="line">138</div><div class="line">139</div><div class="line">140</div><div class="line">141</div><div class="line">142</div><div class="line">143</div><div class="line">144</div><div class="line">145</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">package</span> com.eregg.lucene.search;</div><div class="line"></div><div class="line"><span class="keyword">import</span> java.io.File;</div><div class="line"><span class="keyword">import</span> java.io.IOException;</div><div class="line"></div><div class="line"><span class="keyword">import</span> org.apache.lucene.document.Document;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.index.DirectoryReader;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.index.IndexReader;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.index.Term;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.search.BooleanClause.Occur;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.search.BooleanQuery;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.search.IndexSearcher;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.search.MatchAllDocsQuery;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.search.NumericRangeQuery;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.search.Query;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.search.ScoreDoc;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.search.TermQuery;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.search.TermRangeQuery;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.search.TopDocs;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.store.FSDirectory;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.util.BytesRef;</div><div class="line"><span class="keyword">import</span> org.junit.After;</div><div class="line"><span class="keyword">import</span> org.junit.Before;</div><div class="line"><span class="keyword">import</span> org.junit.Test;</div><div class="line"></div><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">IndexSearchAdvance</span> </span>{</div><div class="line"></div><div class="line"> <span class="keyword">private</span> IndexSearcher indexSearcher;</div><div class="line"> <span class="meta">@Before</span></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">init</span><span class="params">()</span> <span class="keyword">throws</span> Exception</span>{</div><div class="line"> </div><div class="line"> IndexReader reader = DirectoryReader.open(FSDirectory.open(<span class="keyword">new</span> File(<span class="string">“/tmp/lucene/indexdata”</span>)));</div><div class="line"> <span class="keyword">this</span>.indexSearcher = <span class="keyword">new</span> IndexSearcher(reader);</div><div class="line"> }</div><div class="line"> </div><div class="line"> <span class="comment">/<strong></strong></span></div><div class="line"> <em> Term 是最基本的查询方式,域:词 </em></div><div class="line"> <span class="doctag">@throws</span> Exception </div><div class="line"> */</div><div class="line"> <span class="meta">@Test</span></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testTerm</span><span class="params">()</span> <span class="keyword">throws</span> Exception</span>{</div><div class="line"> Query query = <span class="keyword">new</span> TermQuery(<span class="keyword">new</span> Term(<span class="string">“filename”</span>, <span class="string">“lucene”</span>));</div><div class="line"> </div><div class="line"> search(query);</div><div class="line"> </div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">/</span></div><div class="line"> <em> 匹配全部查询</em></div><div class="line"> <span class="doctag">@throws</span> Exception</div><div class="line"> <em>/</em></div><div class="line"> <span class="meta">@Test</span></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testMatchAllDocsQuery</span><span class="params">()</span> <span class="keyword">throws</span> Exception</span>{</div><div class="line"> Query query = <span class="keyword">null</span>;</div><div class="line"> </div><div class="line"> <span class="comment">//1.匹配全部查询</span></div><div class="line"> query = <span class="keyword">new</span> MatchAllDocsQuery();</div><div class="line"> </div><div class="line"> <span class="keyword">this</span>.search(query);</div><div class="line"> </div><div class="line"> }</div><div class="line"> </div><div class="line"> <span class="comment">/**</span></div><div class="line"> 指定项范围内搜索</div><div class="line"> <em> <span class="doctag">@throws</span> Exception</em></div><div class="line"> /</div><div class="line"> <span class="meta">@Test</span></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testTermRangeQuery</span><span class="params">()</span> <span class="keyword">throws</span> Exception</span>{</div><div class="line"> Query query = <span class="keyword">null</span>;</div><div class="line"></div><div class="line"> <span class="comment">//2.指定项范围内搜索</span></div><div class="line"> query = <span class="keyword">new</span> TermRangeQuery(<span class="string">“filename”</span>, <span class="keyword">new</span> BytesRef(<span class="string">“a”</span>.getBytes()), <span class="keyword">new</span> BytesRef(<span class="string">“b”</span>.getBytes()), <span class="keyword">true</span>, <span class="keyword">true</span>);</div><div class="line"> </div><div class="line"> <span class="keyword">this</span>.search(query);</div><div class="line"> </div><div class="line"> }</div><div class="line"> </div><div class="line"> <span class="comment">/<strong></strong></span></div><div class="line"> <em> 指定数字范围查询</em></div><div class="line"> <span class="doctag">@throws</span> Exception</div><div class="line"> */</div><div class="line"> <span class="meta">@Test</span></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testNumericRangeQuery</span><span class="params">()</span> <span class="keyword">throws</span> Exception</span>{</div><div class="line"> Query query = <span class="keyword">null</span>;</div><div class="line"> </div><div class="line"> <span class="comment">//3.指定数字范围查询</span></div><div class="line"> query = NumericRangeQuery.newLongRange(<span class="string">“fileSize”</span>, <span class="number">0l</span>, <span class="number">1000l</span>, <span class="keyword">true</span>, <span class="keyword">true</span>);</div><div class="line"></div><div class="line"> <span class="keyword">this</span>.search(query);</div><div class="line"> </div><div class="line"> }</div><div class="line"> </div><div class="line"> <span class="comment">/</span></div><div class="line"> <em> 组合查询(多条件组合查询)</em></div><div class="line"> <span class="doctag">@throws</span> Exception</div><div class="line"> <em>/</em></div><div class="line"> <span class="meta">@Test</span></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testBooleanQuery</span><span class="params">()</span> <span class="keyword">throws</span> Exception</span>{</div><div class="line"> Query query = <span class="keyword">null</span>;</div><div class="line"> </div><div class="line"> <span class="comment">//4.组合查询(多条件组合查询)</span></div><div class="line"> TermQuery query1 = <span class="keyword">new</span> TermQuery(<span class="keyword">new</span> Term(<span class="string">“filename”</span>, <span class="string">“apache”</span>));</div><div class="line"> NumericRangeQuery<Long> query2 = NumericRangeQuery.newLongRange(<span class="string">“fileSize”</span>, <span class="number">0l</span>, <span class="number">1000l</span>, <span class="keyword">true</span>, <span class="keyword">true</span>);</div><div class="line"> BooleanQuery booleanQuery = <span class="keyword">new</span> BooleanQuery();</div><div class="line"> <span class="comment">//Occur.MUST:必须满足,Occur.MUST_NOT:必须不满足, Occur.SHOULD:或者的关系</span></div><div class="line"> booleanQuery.add(query1, Occur.MUST);</div><div class="line"> booleanQuery.add(query2, Occur.MUST);</div><div class="line"> query = booleanQuery;</div><div class="line"></div><div class="line"> <span class="keyword">this</span>.search(query);</div><div class="line"> </div><div class="line"> }</div><div class="line"></div><div class="line"> </div><div class="line"> <span class="comment">/**</span></div><div class="line"> 该方法分装了查询与输出的功能</div><div class="line"> <em> <span class="doctag">@param</span> query</em></div><div class="line"> <span class="doctag">@throws</span> IOException</div><div class="line"> <em>/</em></div><div class="line"> <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">search</span><span class="params">(Query query)</span> <span class="keyword">throws</span> IOException </span>{</div><div class="line"> System.out.println(<span class="string">“查询条件:”</span>+query);</div><div class="line"> </div><div class="line"> <span class="comment">//TopDocs主要分装了两个字段,总命中数,文档ID</span></div><div class="line"> TopDocs topDocs = indexSearcher.search(query, <span class="number">10</span>);</div><div class="line"> <span class="keyword">int</span> total = topDocs.totalHits;</div><div class="line"> ScoreDoc[] scoreDocs = topDocs.scoreDocs;</div><div class="line"> System.out.println(<span class="string">“查询到的结果数:”</span>+total);</div><div class="line"> <span class="keyword">for</span> (ScoreDoc scoreDoc : scoreDocs) {</div><div class="line"> Document doc = <span class="keyword">this</span>.indexSearcher.doc(scoreDoc.doc);</div><div class="line"> </div><div class="line"> System.out.println(<span class="string">“filename:”</span>+doc.get(<span class="string">“filename”</span>));</div><div class="line"> System.out.println(<span class="string">“filePath:”</span>+doc.get(<span class="string">“filePath”</span>));</div><div class="line"> System.out.println(<span class="string">“fileContent:”</span>+doc.get(<span class="string">“fileContent”</span>));</div><div class="line"> System.out.println(<span class="string">“fileSize:”</span>+doc.get(<span class="string">“fileSize”</span>));</div><div class="line"> </div><div class="line"> System.out.println(<span class="string">“<strong><strong><strong><em>*</em></strong></strong></strong>“</span>);</div><div class="line"> }</div><div class="line"> }</div><div class="line"> </div><div class="line"> <span class="meta">@After</span></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">destroy</span><span class="params">()</span></span>{</div><div class="line"> </div><div class="line"> }</div><div class="line"> </div><div class="line">}</div></pre></td></tr></table></figure>
<h4 id="实例四(IndexQueryParser-查询解析器)"><a href="#实例四(IndexQueryParser-查询解析器)" class="headerlink" title="实例四(IndexQueryParser 查询解析器)"></a><a href="#实例四(IndexQueryParser-查询解析器)" title="实例四(IndexQueryParser 查询解析器)"></a>实例四(IndexQueryParser 查询解析器)</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div><div class="line">82</div><div class="line">83</div><div class="line">84</div><div class="line">85</div><div class="line">86</div><div class="line">87</div><div class="line">88</div><div class="line">89</div><div class="line">90</div><div class="line">91</div><div class="line">92</div><div class="line">93</div><div class="line">94</div><div class="line">95</div><div class="line">96</div><div class="line">97</div><div class="line">98</div><div class="line">99</div><div class="line">100</div><div class="line">101</div><div class="line">102</div><div class="line">103</div><div class="line">104</div><div class="line">105</div><div class="line">106</div><div class="line">107</div><div class="line">108</div><div class="line">109</div><div class="line">110</div><div class="line">111</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">package</span> com.eregg.lucene.queryparser;</div><div class="line"></div><div class="line"><span class="keyword">import</span> java.io.File;</div><div class="line"><span class="keyword">import</span> java.io.IOException;</div><div class="line"><span class="keyword">import</span> java.util.HashMap;</div><div class="line"><span class="keyword">import</span> java.util.Map;</div><div class="line"></div><div class="line"><span class="keyword">import</span> org.apache.lucene.document.Document;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.index.DirectoryReader;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.index.IndexReader;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.queryparser.classic.MultiFieldQueryParser;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.queryparser.classic.QueryParser;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.search.IndexSearcher;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.search.Query;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.search.ScoreDoc;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.search.TopDocs;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.store.Directory;</div><div class="line"><span class="keyword">import</span> org.apache.lucene.store.FSDirectory;</div><div class="line"><span class="keyword">import</span> org.junit.After;</div><div class="line"><span class="keyword">import</span> org.junit.Before;</div><div class="line"><span class="keyword">import</span> org.junit.Test;</div><div class="line"><span class="keyword">import</span> org.wltea.analyzer.lucene.IKAnalyzer;</div><div class="line"></div><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">IndexQueryParser</span> </span>{</div><div class="line"></div><div class="line"> <span class="keyword">private</span> IndexSearcher indexSearcher;</div><div class="line"> </div><div class="line"> <span class="meta">@Before</span></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">init</span><span class="params">()</span> <span class="keyword">throws</span> Exception</span>{</div><div class="line"> Directory directory = FSDirectory.open(<span class="keyword">new</span> File(<span class="string">“/tmp/lucene/indexdata”</span>)); </div><div class="line"> IndexReader reader = DirectoryReader.open(directory); </div><div class="line"> <span class="keyword">this</span>.indexSearcher = <span class="keyword">new</span> IndexSearcher(reader);</div><div class="line"> }</div><div class="line"> </div><div class="line"> <span class="comment">/<strong></strong></span></div><div class="line"> <em> 使用查询解析器 生成 复杂Query,(将查询条件,通过分词器分词,然后组合条件)</em></div><div class="line"> <span class="doctag">@throws</span> Exception </div><div class="line"> */</div><div class="line"> <span class="meta">@Test</span></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testQueryParser</span><span class="params">()</span> <span class="keyword">throws</span> Exception</span>{</div><div class="line"> <span class="comment">/</span></div><div class="line"> <em> 参数一:默认搜索域,参数二:分词器</em></div><div class="line"> /</div><div class="line"> QueryParser queryParser = <span class="keyword">new</span> QueryParser(<span class="string">“filename”</span>, <span class="keyword">new</span> IKAnalyzer());</div><div class="line"> <span class="comment">//parse 中可以不设置域,默认使用创建QueryParser时,指定的默认域(filename)</span></div><div class="line"> Query query = queryParser.parse(<span class="string">“fileContent:全文检索”</span>);</div><div class="line"> <span class="keyword">this</span>.search(query);</div><div class="line"> }</div><div class="line"> </div><div class="line"> <span class="comment">/<strong></strong></span></div><div class="line"> <em> 多个默认域,查询解析器</em></div><div class="line"> <span class="doctag">@throws</span> Exception </div><div class="line"> */</div><div class="line"> <span class="meta">@Test</span></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testMultiFieldQueryParser</span><span class="params">()</span> <span class="keyword">throws</span> Exception</span>{</div><div class="line"> String [] fields = {<span class="string">“filename”</span>, <span class="string">“fileContent”</span>};</div><div class="line"> <span class="comment">//参数一:默认搜索域数组(可以指定多个默认搜索域) 参数2:解析查询短语的分词器</span></div><div class="line"> MultiFieldQueryParser multiFieldQueryParser = <span class="keyword">new</span> MultiFieldQueryParser(fields, <span class="keyword">new</span> IKAnalyzer());</div><div class="line"> Query query = multiFieldQueryParser.parse(<span class="string">“lucene is good”</span>);</div><div class="line"> </div><div class="line"> <span class="keyword">this</span>.search(query);</div><div class="line"> }</div><div class="line"> </div><div class="line"> <span class="comment">/</span></div><div class="line"> <em> 多个默认域,查询解析器,设置域的权重,从而影响排序结果</em></div><div class="line"> <span class="doctag">@throws</span> Exception </div><div class="line"> <em>/</em></div><div class="line"> <span class="meta">@Test</span></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testMultiFieldQueryParserBoosts</span><span class="params">()</span> <span class="keyword">throws</span> Exception</span>{</div><div class="line"> String [] fields = {<span class="string">“filename”</span>, <span class="string">“fileContent”</span>};</div><div class="line"> Map<String, Float> boosts = <span class="keyword">new</span> HashMap<String, Float>();</div><div class="line"> boosts.put(<span class="string">“filename”</span>, <span class="number">1f</span>);</div><div class="line"> boosts.put(<span class="string">“fileContent”</span>, <span class="number">10f</span>);</div><div class="line"> <span class="comment">//参数一:默认搜索域数组(可以指定多个默认搜索域) 参数2:解析查询短语的分词器,参数3:设置域的权重值</span></div><div class="line"> MultiFieldQueryParser multiFieldQueryParser = <span class="keyword">new</span> MultiFieldQueryParser(fields, <span class="keyword">new</span> IKAnalyzer(), boosts);</div><div class="line"> Query query = multiFieldQueryParser.parse(<span class="string">“lucene is good”</span>);</div><div class="line"> </div><div class="line"> <span class="keyword">this</span>.search(query);</div><div class="line"> }</div><div class="line"> </div><div class="line"> </div><div class="line"> <span class="comment">/**</span></div><div class="line"> 该方法分装了查询与输出的功能</div><div class="line"> <em> <span class="doctag">@param</span> query</em></div><div class="line"> <span class="doctag">@throws</span> IOException</div><div class="line"> <em>/</em></div><div class="line"> <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">search</span><span class="params">(Query query)</span> <span class="keyword">throws</span> IOException </span>{</div><div class="line"> System.out.println(<span class="string">“查询条件:”</span>+query);</div><div class="line"> </div><div class="line"> <span class="comment">//TopDocs主要分装了两个字段,总命中数,文档ID</span></div><div class="line"> TopDocs topDocs = indexSearcher.search(query, <span class="number">10</span>);</div><div class="line"> <span class="keyword">int</span> total = topDocs.totalHits;</div><div class="line"> ScoreDoc[] scoreDocs = topDocs.scoreDocs;</div><div class="line"> </div><div class="line"> System.out.println(<span class="string">“查询到的结果数:”</span>+total);</div><div class="line"> <span class="keyword">for</span> (ScoreDoc scoreDoc : scoreDocs) {</div><div class="line"> Document doc = <span class="keyword">this</span>.indexSearcher.doc(scoreDoc.doc);</div><div class="line"> System.out.println(<span class="string">“得分:”</span>+scoreDoc.score);</div><div class="line"> System.out.println(<span class="string">“filename:”</span>+doc.get(<span class="string">“filename”</span>));</div><div class="line"> System.out.println(<span class="string">“filePath:”</span>+doc.get(<span class="string">“filePath”</span>));</div><div class="line"> System.out.println(<span class="string">“fileContent:”</span>+doc.get(<span class="string">“fileContent”</span>));</div><div class="line"> System.out.println(<span class="string">“fileSize:”</span>+doc.get(<span class="string">“fileSize”</span>));</div><div class="line"> </div><div class="line"> System.out.println(<span class="string">“<strong><strong><strong><em>*</em></strong></strong></strong>“</span>);</div><div class="line"> }</div><div class="line"> }</div><div class="line"> <span class="meta">@After</span></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">destory</span><span class="params">()</span></span>{</div><div class="line"> </div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</div>
</article>
<article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
<div class="post-block">
<link itemprop="mainEntityOfPage" href="http://eregg.com/2016/11/22/zookeeper/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="name" content="eregg">
<meta itemprop="description" content="">
<meta itemprop="image" content="/uploads/avatar.jpg">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="学不可以已">
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2016/11/22/zookeeper/" itemprop="url">zookeeper</a></h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建于" itemprop="dateCreated datePublished" datetime="2016-11-22T09:40:44+08:00">
2016-11-22
</time>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h4 id="zookeeper概述"><a href="#zookeeper概述" class="headerlink" title="zookeeper概述"></a><a href="#zookeeper概述" title="zookeeper概述"></a>zookeeper概述</h4><h5 id="什么是zookpeer"><a href="#什么是zookpeer" class="headerlink" title="什么是zookpeer"></a><a href="#什么是zookpeer" title="什么是zookpeer"></a>什么是zookpeer</h5><blockquote>
<p>zookpeer是一个项目协调框架,分布式应用可以基于它实现同步服务。</p>
</blockquote>
<h5 id="zookpeer可以做什么"><a href="#zookpeer可以做什么" class="headerlink" title="zookpeer可以做什么"></a><a href="#zookpeer可以做什么" title="zookpeer可以做什么"></a>zookpeer可以做什么</h5><blockquote>
<p>为分布式应用提供集群协调服务</p>
<p>为客户端保存数据,提供监听</p>
<p>具体案例如:<br>Hadoop2.0,使用Zookeeper的事件处理确保整个集群只有一个活跃的NameNode,存储配置信息等.<br>HBase,使用Zookeeper的事件处理确保整个集群只有一个HMaster,察觉HRegionServer联机和宕机,存储访问控制列表等.</p>
</blockquote>
<h5 id="zookpeer集群机制"><a href="#zookpeer集群机制" class="headerlink" title="zookpeer集群机制"></a><a href="#zookpeer集群机制" title="zookpeer集群机制"></a>zookpeer集群机制</h5><blockquote>
<p>半数机制:集群中半数以上机器存活,集群可用。</p>
</blockquote>
<h4 id="安装zookpeer"><a href="#安装zookpeer" class="headerlink" title="安装zookpeer"></a><a href="#安装zookpeer" title="安装zookpeer"></a>安装zookpeer</h4><h5 id="机器部署"><a href="#机器部署" class="headerlink" title="机器部署"></a><a href="#机器部署" title="机器部署"></a>机器部署</h5><blockquote>
<p>安装到3台虚拟机上</p>
</blockquote>
<h5 id="上传"><a href="#上传" class="headerlink" title="上传"></a><a href="#上传" title="上传"></a>上传</h5><blockquote>
<p>使用上传工具将zookeeper-3.4.5.tar.gz上传至其中一台服务器(等配置完成后再分发给其他机器)</p>
</blockquote>
<h5 id="解压"><a href="#解压" class="headerlink" title="解压"></a><a href="#解压" title="解压"></a>解压</h5><figure class="highlight stylus"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ tar -zxvf zookeeper-<span class="number">3.4</span>.<span class="number">5</span><span class="selector-class">.tar</span><span class="selector-class">.gz</span> -C ~/app/</div></pre></td></tr></table></figure>
<h5 id="修改配置文件"><a href="#修改配置文件" class="headerlink" title="修改配置文件"></a><a href="#修改配置文件" title="修改配置文件"></a>修改配置文件</h5><figure class="highlight awk"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line">cd ~<span class="regexp">/app/</span>zookeeper-<span class="number">3.4</span>.<span class="number">5</span><span class="regexp">/conf/</span></div><div class="line">cp zoo_sample.cfg zoo.cfg</div><div class="line">vi zoo.cfg</div><div class="line"><span class="comment">#添加内容</span></div><div class="line">dataDir=<span class="regexp">/root/</span>app<span class="regexp">/zookeeper-3.4.5/</span>data</div><div class="line">dataLogDir=<span class="regexp">/root/</span>app<span class="regexp">/zookeeper-3.4.5/</span>log (可选)</div><div class="line">server.<span class="number">1</span>= server01:<span class="number">2888</span>:<span class="number">3888</span> (心跳端口、数据端口)</div><div class="line">server.<span class="number">2</span>= server02:<span class="number">2888</span>:<span class="number">3888</span></div><div class="line">server.<span class="number">3</span>= server03:<span class="number">2888</span>:<span class="number">3888</span></div></pre></td></tr></table></figure><br>> 创建文件夹mkdir /root/app/zookeeper-3.4.5/data<br>><br>> 在data文件夹下新建myid文件,myid的文件内容为<br><figure class="highlight lsl"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">echo <span class="number">1</span> > /root/app/ zookeeper<span class="number">-3.4</span><span class="number">.5</span>/data/myid</div></pre></td></tr></table></figure>
<h5 id="将配置好的安装包分发到其他机器上"><a href="#将配置好的安装包分发到其他机器上" class="headerlink" title="将配置好的安装包分发到其他机器上"></a><a href="#将配置好的安装包分发到其他机器上" title="将配置好的安装包分发到其他机器上"></a>将配置好的安装包分发到其他机器上</h5><figure class="highlight groovy"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">scp -r <span class="regexp">/root/</span>app<span class="regexp">/zookeeper-3.4.5/</span> <span class="string">server02:</span><span class="regexp">/root/</span>app/</div><div class="line">scp -r <span class="regexp">/root/</span>app<span class="regexp">/zookeeper-3.4.5/</span> <span class="string">server03:</span><span class="regexp">/root/</span>app/</div></pre></td></tr></table></figure>
<h5 id="修改其他机器的配置文件"><a href="#修改其他机器的配置文件" class="headerlink" title="修改其他机器的配置文件"></a><a href="#修改其他机器的配置文件" title="修改其他机器的配置文件"></a>修改其他机器的配置文件</h5><blockquote>
<p>到server02上:修改myid为:2</p>
<figure class="highlight lsl"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">echo <span class="number">2</span> > /root/app/zookeeper<span class="number">-3.4</span><span class="number">.5</span>/data/myid</div></pre></td></tr></table></figure><br>到server03上:修改myid为:3<br><figure class="highlight lsl"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">echo <span class="number">3</span> > /root/app/zookeeper<span class="number">-3.4</span><span class="number">.5</span>/data/myid</div></pre></td></tr></table></figure>
</blockquote>
<h5 id="启动zookeeper"><a href="#启动zookeeper" class="headerlink" title="启动zookeeper"></a><a href="#启动zookeeper" title="启动zookeeper"></a>启动zookeeper</h5><blockquote>
<p>先在各台机器上关闭防火墙</p>
<figure class="highlight nginx"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="attribute">service</span> iptables stop</div><div class="line">chkconfig iptables <span class="literal">off</span></div></pre></td></tr></table></figure><br>到每一台服务器上启动zk的服务节点<br><figure class="highlight awk"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="regexp">/root/</span>app<span class="regexp">/zookeeper-3.4.5/</span>bin<span class="regexp">/zkServer.sh start</span></div></pre></td></tr></table></figure>
</blockquote>
<h5 id="查看集群状态"><a href="#查看集群状态" class="headerlink" title="查看集群状态"></a><a href="#查看集群状态" title="查看集群状态"></a>查看集群状态</h5><ol>
<li><p>jps(查看进程)</p>
<figure class="highlight lsl"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">[root@server01 zookeeper<span class="number">-3.4</span><span class="number">.5</span>]# jps</div><div class="line"><span class="number">1837</span> QuorumPeerMain</div><div class="line"><span class="number">2113</span> Jps</div></pre></td></tr></table></figure>
</li>
<li><p>zkServer.sh status(查看集群状态,主从信息)</p>
<figure class="highlight dts"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">[root@server01 zookeeper<span class="number">-3.4</span><span class="number">.5</span>]<span class="meta"># ./bin/zkServer.sh status</span></div><div class="line">JMX enabled by default</div><div class="line">Using config: <span class="meta-keyword">/root/</span>app/zookeeper<span class="number">-3.4</span><span class="number">.5</span><span class="meta-keyword">/bin/</span>..<span class="meta-keyword">/conf/</span>zoo.cfg</div><div class="line"><span class="symbol">Mode:</span> follower</div></pre></td></tr></table></figure>
</li>
</ol>
<h4 id="zookeeper的结构和命令"><a href="#zookeeper的结构和命令" class="headerlink" title="zookeeper的结构和命令"></a><a href="#zookeeper的结构和命令" title="zookeeper的结构和命令"></a>zookeeper的结构和命令</h4><h5 id="zookeeper数据结构"><a href="#zookeeper数据结构" class="headerlink" title="zookeeper数据结构"></a><a href="#zookeeper数据结构" title="zookeeper数据结构"></a>zookeeper数据结构</h5><ol>
<li>层次化的目录结构,命名符合常规文件系统规范</li>
<li>每个节点在zookeeper中叫做znode,并且其有一个唯一的路径标识</li>
<li>节点Znode可以包含数据和子节点</li>
<li>客户端应用可以在节点上设置监视器</li>
</ol>
<h5 id="节点类型"><a href="#节点类型" class="headerlink" title="节点类型"></a><a href="#节点类型" title="节点类型"></a>节点类型</h5><blockquote>
<p>Znode有两种类型:</p>
</blockquote>
<ol>
<li>短暂(ephemeral)(客户端断开连接,zookeeper会帮客户端把znode删除)</li>
<li>持久(persistent)(断开连接不删除)<blockquote>
<p>Znode有四种形式的目录节点(默认是persistent )</p>
<ol>
<li>PERSISTENT</li>
<li>PERSISTENT_SEQUENTIAL(持久序列/test0000000019 )</li>
<li>EPHEMERAL</li>
<li>EPHEMERAL_SEQUENTIAL</li>
</ol>
<p>创建znode时设置顺序标识,znode名称后会附加一个值<br>顺序号是一个单调递增的计数器,由父节点维护<br>在分布式系统中,顺序号可以被用于为所有的事件进行全局排序,这样客户端可以通过顺序号推断事件的顺序</p>
</blockquote>
</li>
</ol>
<h5 id="zookeeper特性"><a href="#zookeeper特性" class="headerlink" title="zookeeper特性"></a><a href="#zookeeper特性" title="zookeeper特性"></a>zookeeper特性</h5><ul>
<li>Zookeeper:一个leader,多个follower组成的集群</li>
<li>全局数据一致:每个server保存一份相同的数据副本,client无论连接到哪个server,数据都是一致的</li>
<li>分布式读写,更新请求转发,由leader实施</li>
<li>更新请求顺序进行,来自同一个client的更新请求按其发送顺序依次执行</li>
<li>数据更新原子性,一次数据更新要么成功,要么失败</li>
<li>实时性,在一定时间范围内,client能读到最新数据</li>
</ul>
<h5 id="zookpeer命令操作"><a href="#zookpeer命令操作" class="headerlink" title="zookpeer命令操作"></a><a href="#zookpeer命令操作" title="zookpeer命令操作"></a>zookpeer命令操作</h5><figure class="highlight sql"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div></pre></td><td class="code"><pre><div class="line">[zk: localhost:2181(CONNECTED) 0] <span class="keyword">help</span></div><div class="line">ZooKeeper -<span class="keyword">server</span> host:port cmd args</div><div class="line"> <span class="keyword">connect</span> host:port</div><div class="line"> <span class="keyword">get</span> <span class="keyword">path</span> [watch]</div><div class="line"> ls <span class="keyword">path</span> [watch]</div><div class="line"> <span class="keyword">set</span> <span class="keyword">path</span> <span class="keyword">data</span> [<span class="keyword">version</span>]</div><div class="line"> rmr <span class="keyword">path</span></div><div class="line"> delquota [-n|-b] <span class="keyword">path</span></div><div class="line"> quit </div><div class="line"> printwatches <span class="keyword">on</span>|<span class="keyword">off</span></div><div class="line"> <span class="keyword">create</span> [-s] [-e] <span class="keyword">path</span> <span class="keyword">data</span> acl </div><div class="line"> stat <span class="keyword">path</span> [watch]</div><div class="line"> <span class="keyword">close</span> </div><div class="line"> ls2 <span class="keyword">path</span> [watch]</div><div class="line"> history </div><div class="line"> listquota <span class="keyword">path</span></div><div class="line"> setAcl <span class="keyword">path</span> acl</div><div class="line"> getAcl <span class="keyword">path</span></div><div class="line"> <span class="keyword">sync</span> <span class="keyword">path</span></div><div class="line"> <span class="keyword">redo</span> cmdno</div><div class="line"> addauth scheme auth</div><div class="line"> <span class="keyword">delete</span> <span class="keyword">path</span> [<span class="keyword">version</span>]</div><div class="line"> setquota -n|-b val <span class="keyword">path</span></div></pre></td></tr></table></figure><br>> create [-s] [-e] path data acl<br>><br>> -s:sequential序列节点:会在全局维护一个序列号<br>> Zk会为sequential类节点维护一个全局序列号<br>><br>> -e:短暂的。 不带参数就是非短暂的<br>><br>> <em> 短暂的znode(创建者客户端一旦断开连接,zk就会删除这个节点)<br>> </em> 持久的znode(不管创建者客户端是否断开,znode一致存在,除非手动删除)<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">创建短暂非序列化节点:<span class="_">-e</span></div><div class="line">创建短暂序列化:<span class="_">-s</span> –e</div><div class="line">创建持久非序列化:空</div><div class="line">创建持久序列化:<span class="_">-s</span></div></pre></td></tr></table></figure>
<ol>
<li><p>使用 ls 命令来查看当前 ZooKeeper 中所包含的内容:</p>
<figure class="highlight scheme"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">[<span class="name">zk:</span> localhost:2181(<span class="name">CONNECTED</span>) <span class="number">2</span>] ls /</div><div class="line">[<span class="name">test</span>, test2, zookeeper]</div></pre></td></tr></table></figure>
</li>
<li><p>创建一个新的 znode ,使用 create /myData 。这个命令创建了一个新的 znode 节点“ zk ”以及与它关联的字符串:</p>
<figure class="highlight haxe"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">[zk: <span class="type">localhost</span>:<span class="number">2181</span>(CONNECTED) <span class="number">0</span>] create /<span class="keyword">new</span><span class="type">node</span> nodedata</div><div class="line">Created /<span class="keyword">new</span><span class="type">node</span></div></pre></td></tr></table></figure>
</li>
<li><p>我们运行 get 命令来确认 znode 是否包含我们所创建的字符串:</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line">[zk: localhost:2181(CONNECTED) 2] get /newnode</div><div class="line">nodedata</div><div class="line">cZxid = 0x200000040</div><div class="line">ctime = Wed Jul 06 14:13:40 EDT 2016</div><div class="line">mZxid = 0x200000040</div><div class="line">mtime = Wed Jul 06 14:13:40 EDT 2016</div><div class="line">pZxid = 0x200000040</div><div class="line">cversion = 0</div><div class="line">dataVersion = 0</div><div class="line">aclVersion = 0</div><div class="line">ephemeralOwner = 0x0</div><div class="line">dataLength = 8</div><div class="line">numChildren = 0</div></pre></td></tr></table></figure>
</li>
<li><p>下面我们通过 set 命令来对 zk 所关联的字符串进行设置:</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line">[zk: localhost:2181(CONNECTED) 3] set /newnode updatevalue</div><div class="line">cZxid = 0x200000040</div><div class="line">ctime = Wed Jul 06 14:13:40 EDT 2016</div><div class="line">mZxid = 0x200000041</div><div class="line">mtime = Wed Jul 06 14:14:39 EDT 2016</div><div class="line">pZxid = 0x200000040</div><div class="line">cversion = 0</div><div class="line">dataVersion = 1</div><div class="line">aclVersion = 0</div><div class="line">ephemeralOwner = 0x0</div><div class="line">dataLength = 11</div><div class="line">numChildren = 0</div></pre></td></tr></table></figure>
</li>
<li><p>下面我们将刚才创建的 znode 删除:</p>
<figure class="highlight scheme"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">[<span class="name">zk:</span> localhost:2181(<span class="name">CONNECTED</span>) <span class="number">6</span>] delete /newnode</div></pre></td></tr></table></figure></li>
</ol>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</div>
</article>
<article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
<div class="post-block">
<link itemprop="mainEntityOfPage" href="http://eregg.com/2016/11/22/signal信号/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="name" content="eregg">
<meta itemprop="description" content="">
<meta itemprop="image" content="/uploads/avatar.jpg">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="学不可以已">
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2016/11/22/signal信号/" itemprop="url">signal信号</a></h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建于" itemprop="dateCreated datePublished" datetime="2016-11-22T09:40:27+08:00">
2016-11-22
</time>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h3 id="信号基本概念"><a href="#信号基本概念" class="headerlink" title="信号基本概念"></a><a href="#信号基本概念" title="信号基本概念"></a>信号基本概念</h3><blockquote>
<p>信号是软件中断,很多比较重要的应用程序都需要处理信号,信号提供了一种处理异步事件的方法,<br>例如,终端用户键入中断键,会通过信号机制停止一个程序。<br>首先,每一个信号都有一个名字,这些名字都是以3个字符SIG开头,例如,SIGABRT是夭折信号,<br>当进程调用abort函数时产生这种信号,SIGALRM是闹钟信号,由alarm函数设置的定时器超时后将产生此信号。</p>
</blockquote>
<h3 id="有很多种情况下可以产生信号"><a href="#有很多种情况下可以产生信号" class="headerlink" title="有很多种情况下可以产生信号"></a><a href="#有很多种情况下可以产生信号" title="有很多种情况下可以产生信号"></a>有很多种情况下可以产生信号</h3><ol>
<li>当用户按下终端键时,引发终端产生的信号,在终端上按下Ctrl+c,可以产生中断信号</li>
<li>硬件异常产生信号,除数为0,无效的内存引用等<br>例如对执行一个无效内存引用的进程产生SIGSEGV信号。</li>
<li>进程调用kill()函数可将任意信号发送给任意进程</li>
<li>调用kill命令,与3效果一样。</li>
<li>当检测到某种软件条件已经发生,并应将其通知有关进程也产生信号,<br>例如 在管道的读端进程已经终止后,写进程将收到一个SIGPIPE信号<br>当进程中调用了alarm函数,当定时器超时会产生一个SIGALRM信号<blockquote>
<p><strong><em>产生信号的事件对进程而言是随机出现的,进程不能简单测试一个变量来判断是否发生了一个信号,<br>而是必须提前告诉内核,在”此“信号发生时,该怎么处理。</em></strong></p>
</blockquote>
</li>
</ol>
<h3 id="处理信号的三种行为"><a href="#处理信号的三种行为" class="headerlink" title="处理信号的三种行为"></a><a href="#处理信号的三种行为" title="处理信号的三种行为"></a>处理信号的三种行为</h3><ol>
<li>忽略此信号</li>
<li>捕捉信号</li>
<li>执行系统默认动作> 信号默认处理的5种行为,对于大多数信号的系统默认动作是终止该进程。</li>
</ol>
<ul>
<li>Term Default action is to terminate the process.终止当前进程</li>
<li>Ign Default action is to ignore the signal.忽略这个信号</li>
<li>Core Default action is to terminate the process and dump core (see core(5)). 终止当前进程并且生成一个core文件</li>
<li>Stop Default action is to stop the process.暂停当前进程</li>
<li>Cont Default action is to continue the process if it is currently stopped.继续当前进程</li>
</ul>
<h3 id="信号的种类"><a href="#信号的种类" class="headerlink" title="信号的种类"></a><a href="#信号的种类" title="信号的种类"></a>信号的种类</h3><p><img src="http://123.57.181.198/images/signal/1.jpg" alt="信号的种类"></p>
<h3 id="信号集"><a href="#信号集" class="headerlink" title="信号集"></a><a href="#信号集" title="信号集"></a>信号集</h3><p><img src="http://123.57.181.198/images/signal/2.png" alt="信号集"></p>
<blockquote>
<p>信号集位于系统内核PCB进程控制块</p>
<ul>
<li>未决信号集,由内核自动控制,用户只有只读权限,不可以修改该信号集</li>
<li>阻塞信号集,又称信号屏蔽字,该信号集由用户设置,</li>
<li>信号处理动作,</li>
</ul>
<ol>
<li>执行默认动作,</li>
<li>忽略信号,</li>
<li>捕捉 注意:SIGKILL和SIGSTOP不能被捕捉</li>
</ol>
</blockquote>
<h3 id="信号控制原语"><a href="#信号控制原语" class="headerlink" title="信号控制原语"></a><a href="#信号控制原语" title="信号控制原语"></a>信号控制原语</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">sigemptyset</span><span class="params">(<span class="keyword">sigset_t</span> <em><span class="built_in">set</span>)</em></span></span>;将信号集清空</div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">sigfillset</span><span class="params">(<span class="keyword">sigset_t</span> <span class="built_in">set</span>)</span></span>;initializes <span class="built_in">set</span> to full, including all signals.</div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">sigaddset</span><span class="params">(<span class="keyword">sigset_t</span> <em><span class="built_in">set</span>, <span class="keyword">int</span> signum)</em></span></span>;向信号集添加一个信号</div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">sigdelset</span><span class="params">(<span class="keyword">sigset_t</span> <span class="built_in">set</span>, <span class="keyword">int</span> signum)</span></span>;从信号集删除一个信号</div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">sigismember</span><span class="params">(<span class="keyword">const</span> <span class="keyword">sigset_t</span> *<span class="built_in">set</span>, <span class="keyword">int</span> signum)</span></span>;判断信号集是否包含一个信号</div></pre></td></tr></table></figure>
<h3 id="设置屏蔽字函数"><a href="#设置屏蔽字函数" class="headerlink" title="设置屏蔽字函数"></a><a href="#设置屏蔽字函数" title="设置屏蔽字函数"></a>设置屏蔽字函数</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">sigprocmask</span><span class="params">(<span class="keyword">int</span> how, <span class="keyword">const</span> <span class="keyword">sigset_t</span> <em><span class="built_in">set</span>, <span class="keyword">sigset_t</span> </em>oldset)</span></span>;将一个信号集设置到阻塞信号集中</div><div class="line">首先,若oldset是非空指针,那么进程的当前信号屏蔽字通过oldset返回。</div><div class="line">其次,若<span class="built_in">set</span>是个一个非空指针,则参数how指示如何修改当前的信号屏蔽字,</div><div class="line">how的可选值,SIG_BLOCK是或的操作,而SIG_SETMASK则是赋值操作。</div><div class="line">注意,不能阻塞SIGKILL和SIGSTOP信号。</div></pre></td></tr></table></figure>
<p><img src="http://123.57.181.198/images/signal/3.png" alt=""></p>
<h3 id="设置信号捕捉动作"><a href="#设置信号捕捉动作" class="headerlink" title="设置信号捕捉动作"></a><a href="#设置信号捕捉动作" title="设置信号捕捉动作"></a>设置信号捕捉动作</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">sigaction</span><span class="params">(<span class="keyword">int</span> signum, <span class="keyword">const</span> <span class="keyword">struct</span> sigaction <em>act, <span class="keyword">struct</span> sigaction </em>oldact)</span></span>;</div><div class="line">其中,参数signum是要检测或者修改其具体动作信号的编号,若act指针非空,则要修改其动作,</div><div class="line">如果oldset指针非空,则系统经由oldact指针返回该信号的上一个动作,此函数使用到的结构体如下:</div><div class="line"><span class="keyword">struct</span> sigaction {</div><div class="line"> <span class="keyword">void</span> (<em>sa_handler)(<span class="keyword">int</span>);<span class="comment">//信号处理程序的地址,或者SIG_IGN,或者SIG_DEF</span></em></div><div class="line"> <span class="keyword">void</span> (sa_sigaction)(<span class="keyword">int</span>, <span class="keyword">siginfo_t</span> <em>, <span class="keyword">void</span> </em>);</div><div class="line"> <span class="keyword">sigset_t</span> sa_mask;<span class="comment">//添加到信号屏蔽字的集合</span></div><div class="line"> <span class="keyword">int</span> sa_flags;</div><div class="line"> };</div><div class="line">当更改信号动作时,如果sa_handler字段包含一个信号捕捉函数地址(不是常量SIG_IGN或SIG_DEF),</div><div class="line">则sa_mask字段说明了一个信号集,在调用该信号捕捉函数之前,这一信号集要加到进程的信号屏蔽字中,</div><div class="line">仅当从信号捕捉函数返回时在将进程的信号屏蔽字恢复为原先值。</div></pre></td></tr></table></figure>
<p><img src="http://123.57.181.198/images/signal/1.jpg" alt=""></p>
<blockquote>
<p>举例理解上图<br>假设你正在做饭,期间有电话打进来(收到一个电话信号),此时你有三种回应,</p>
<ol>
<li>挂断电话,相当于执行了SIG_ING动作</li>
<li>无视电话,此时手机会执行一个默认动作就是挂机,然后显示未接电话,相当于执行了SIG_DEF动作(挂断,生成core文件)</li>
<li>接听电话,此时手机就需要你说话的功能(相当于系统调用用户处理函数),当你说完以后执行了挂机操作(相当于调用了sigreturn,返回内核),手机执行挂机操作,然后显示挂机成功(相当于调用,sys_sigreturn),此时的你又回到厨房继续做饭。</li>
</ol>
</blockquote>
<h3 id="实例一(信号屏蔽字)"><a href="#实例一(信号屏蔽字)" class="headerlink" title="实例一(信号屏蔽字)"></a><a href="#实例一(信号屏蔽字)" title="实例一(信号屏蔽字)"></a>实例一(信号屏蔽字)</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdio.h></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdlib.h></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><unistd.h></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><signal.h></span></span></div><div class="line"></div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">printsigset</span><span class="params">(<span class="keyword">const</span> <span class="keyword">sigset_t</span>* <span class="built_in">set</span>)</span></span>{</div><div class="line"> </div><div class="line"> <span class="keyword">int</span> i;</div><div class="line"> <span class="keyword">for</span>(i = <span class="number">1</span>; i < <span class="number">32</span>; i++){</div><div class="line"> <span class="keyword">if</span>(i % <span class="number">4</span> == <span class="number">0</span>){ </div><div class="line"> <span class="built_in">putchar</span>(<span class="string">‘ ‘</span>);</div><div class="line"> } </div><div class="line"> <span class="keyword">if</span>(sigismember(<span class="built_in">set</span>, i) == <span class="number">1</span>){ </div><div class="line"> <span class="built_in">putchar</span>(<span class="string">‘1’</span>);</div><div class="line"> }<span class="keyword">else</span>{</div><div class="line"> <span class="built_in">putchar</span>(<span class="string">‘0’</span>);</div><div class="line"> } </div><div class="line"> } </div><div class="line"> <span class="built_in">puts</span>(<span class="string">“”</span>);</div><div class="line">}</div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">(<span class="keyword">void</span>)</span></span>{</div><div class="line"> </div><div class="line"> <span class="keyword">sigset_t</span> s, p;</div><div class="line"> <span class="comment">//1.清空信号集</span></div><div class="line"> sigemptyset(&s);</div><div class="line"> <span class="comment">//2.添加信号到信号集</span></div><div class="line"> sigaddset(&s, SIGINT);</div><div class="line"> sigaddset(&s, SIGQUIT);</div><div class="line"> <span class="comment">//3.设置信号集到阻塞信号集</span></div><div class="line"> sigprocmask(SIG_BLOCK, &s, <span class="literal">NULL</span>);</div><div class="line"></div><div class="line"> <span class="keyword">while</span>(<span class="number">1</span>){</div><div class="line"> <span class="comment">//1.获取未决信号集</span></div><div class="line"> sigpending(&p);</div><div class="line"> <span class="comment">//2.打印未决信号集</span></div><div class="line"> printsigset(&p);</div><div class="line"> sleep(<span class="number">1</span>);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> <span class="number">0</span>;</div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="实例二(信号捕捉函数)"><a href="#实例二(信号捕捉函数)" class="headerlink" title="实例二(信号捕捉函数)"></a><a href="#实例二(信号捕捉函数)" title="实例二(信号捕捉函数)"></a>实例二(信号捕捉函数)</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdio.h></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdlib.h></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><unistd.h></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><signal.h></span></span></div><div class="line"></div><div class="line"></div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">do_sig</span><span class="params">(<span class="keyword">int</span> num)</span></span>{</div><div class="line"> <span class="built_in">printf</span>(<span class="string">“ i am do_sig, handing %d\n”</span>, num);</div><div class="line"> sleep(<span class="number">15</span>);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">printsigset</span><span class="params">(<span class="keyword">const</span> <span class="keyword">sigset_t</span>* <span class="built_in">set</span>)</span></span>{</div><div class="line"></div><div class="line"> <span class="keyword">int</span> i;</div><div class="line"> <span class="keyword">for</span>(i = <span class="number">1</span>; i < <span class="number">32</span>; i++){</div><div class="line"> <span class="keyword">if</span>(sigismember(<span class="built_in">set</span>, i) == <span class="number">1</span>){ </div><div class="line"> <span class="built_in">putchar</span>(<span class="string">‘1’</span>);</div><div class="line"> }<span class="keyword">else</span>{</div><div class="line"> <span class="built_in">putchar</span>(<span class="string">‘0’</span>);</div><div class="line"> } </div><div class="line"> <span class="keyword">if</span>(i % <span class="number">4</span> == <span class="number">0</span>){ </div><div class="line"> <span class="built_in">putchar</span>(<span class="string">‘ ‘</span>);</div><div class="line"> } </div><div class="line"> } </div><div class="line"> <span class="built_in">puts</span>(<span class="string">“”</span>);</div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">(<span class="keyword">void</span>)</span></span>{</div><div class="line"> </div><div class="line"> <span class="comment">//1.设置捕捉函数</span></div><div class="line"> <span class="comment">//创建一个sigaction变量</span></div><div class="line"> <span class="keyword">struct</span> sigaction act;</div><div class="line"> <span class="comment">//指定处理函</span></div><div class="line"> act.sa_handler = do_sig;</div><div class="line"> <span class="comment">//零时清空,信号屏蔽字</span></div><div class="line"> sigemptyset(&act.sa_mask);</div><div class="line"> <span class="comment">//调用sigaction捕捉函数,将包含捕捉函数的act变量传入,实现函数捕捉功能</span></div><div class="line"> sigaction(SIGINT, &act, <span class="literal">NULL</span>);</div><div class="line"> </div><div class="line"> <span class="comment">//2.设置信号屏蔽字</span></div><div class="line"> <span class="comment">////定义一个信号集</span></div><div class="line"> <span class="keyword">sigset_t</span> <span class="built_in">set</span>, p;</div><div class="line"> <span class="comment">//清空信号集</span></div><div class="line"> sigemptyset(&<span class="built_in">set</span>);</div><div class="line"> <span class="comment">//向信号集添加一个信号SIGINT</span></div><div class="line"> <span class="comment">//sigaddset(&set, SIGINT);</span></div><div class="line"> sigaddset(&<span class="built_in">set</span>, SIGQUIT);</div><div class="line"> <span class="comment">//将信号集应用到信号阻塞集</span></div><div class="line"> sigprocmask(SIG_BLOCK, &<span class="built_in">set</span>, <span class="literal">NULL</span>);</div><div class="line"> <span class="keyword">while</span>(<span class="number">1</span>){</div><div class="line"> <span class="comment">//获取未决信号集</span></div><div class="line"> sigpending(&p);</div><div class="line"> printsigset(&p);</div><div class="line"> sleep(<span class="number">1</span>);</div><div class="line"> } </div><div class="line"> <span class="keyword">return</span> <span class="number">0</span>;</div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="实例三(sigchild-c)"><a href="#实例三(sigchild-c)" class="headerlink" title="实例三(sigchild.c)"></a><a href="#实例三(sigchild-c)" title="实例三(sigchild.c)"></a>实例三(sigchild.c)</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdio.h></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdlib.h></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><unistd.h></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><signal.h></span></span></div><div class="line"></div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">do_sig_child</span><span class="params">(<span class="keyword">int</span> num)</span></span>{</div><div class="line"> <span class="keyword">pid_t</span> pid;</div><div class="line"> <span class="keyword">int</span> status;</div><div class="line"> <span class="comment">//此处必须加while循环,否则会出现僵尸进程</span></div><div class="line"> <span class="comment">//信号不支持排队,当正在执行SIGCHLD捕捉函数时,在过来一个或多个SIGCHLD信号怎么不?</span></div><div class="line"> <span class="comment">//所以使用轮询解决</span></div><div class="line"> <span class="keyword">while</span>((pid = waitpid(<span class="number">0</span>, &status, WNOHANG)) > <span class="number">0</span>){ </div><div class="line"> <span class="keyword">if</span>(WIFEXITED(status)){</div><div class="line"> <span class="built_in">printf</span>(<span class="string">“current pid %d child %d exit %d\n”</span>, getpid(), pid, WEXITSTATUS(status));</div><div class="line"> }<span class="keyword">else</span> <span class="keyword">if</span>(WIFSIGNALED(status)){</div><div class="line"> <span class="built_in">printf</span>(<span class="string">“child %d cancel signal %d\n”</span>, pid, WTERMSIG(status));</div><div class="line"> } </div><div class="line"> } </div><div class="line"> <span class="built_in">printf</span>(<span class="string">“<strong><strong><strong><strong><strong>**</strong></strong></strong></strong></strong>pid %d\n”</span>, pid);</div><div class="line">}</div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span>{</div><div class="line"></div><div class="line"> <span class="keyword">pid_t</span> pid;</div><div class="line"> <span class="keyword">int</span> i;</div><div class="line"> <span class="comment">//阻塞SIGCHLD信号,解决时序竞态产生的bug</span></div><div class="line"> <span class="keyword">sigset_t</span> <span class="built_in">set</span>, oldset;</div><div class="line"> sigemptyset(&<span class="built_in">set</span>);</div><div class="line"> sigaddset(&<span class="built_in">set</span>, SIGCHLD);</div><div class="line"> sigprocmask(SIG_BLOCK, &<span class="built_in">set</span>, &oldset);</div><div class="line"> <span class="comment">//创建10个子进程</span></div><div class="line"> <span class="keyword">for</span>(i = <span class="number">0</span>; i < <span class="number">10</span>; i++){</div><div class="line"> <span class="keyword">if</span>((pid = fork()) == <span class="number">0</span>){</div><div class="line"> <span class="keyword">break</span>;</div><div class="line"> }<span class="keyword">else</span> <span class="keyword">if</span>(pid < <span class="number">0</span>){</div><div class="line"> perror(<span class="string">“fork”</span>);</div><div class="line"> <span class="built_in">exit</span>(<span class="number">1</span>);</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">//子进程</span></div><div class="line"> <span class="keyword">if</span>(pid == <span class="number">0</span>){</div><div class="line"> <span class="keyword">int</span> n = <span class="number">1</span>;</div><div class="line"> <span class="keyword">while</span>(n–){</div><div class="line"> <span class="built_in">printf</span>(<span class="string">“child ID %d\n”</span>, getpid());</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> i;</div><div class="line"> }<span class="keyword">else</span> <span class="keyword">if</span>(pid > <span class="number">0</span>){</div><div class="line"> sleep(<span class="number">1</span>);</div><div class="line"> <span class="comment">//捕捉SIGCHLD信号,回收子进程</span></div><div class="line"> <span class="comment">//1.定义一个sigaction变量</span></div><div class="line"> <span class="keyword">struct</span> sigaction act;</div><div class="line"> <span class="comment">//2.设置捕捉函数</span></div><div class="line"> act.sa_handler = do_sig_child;</div><div class="line"> <span class="comment">//3.情况屏蔽字</span></div><div class="line"> sigemptyset(&act.sa_mask);</div><div class="line"> <span class="comment">//sigaddset(&act.sa_mask, SIGCHLD);</span></div><div class="line"> <span class="comment">//通过sigaction函数,设置要捕捉的信号,及捕捉函数</span></div><div class="line"> sigaction(SIGCHLD, &act, <span class="literal">NULL</span>);</div><div class="line"> <span class="comment">//解除对SIGCHLD信号的阻塞,解决时序竞态产生的bug</span></div><div class="line"> sigprocmask(SIG_SETMASK, &oldset, <span class="literal">NULL</span>);</div><div class="line"> <span class="comment">//此时的父进程就无需轮询等待回收子进程了,可以做其他事情</span></div><div class="line"> <span class="keyword">while</span>(<span class="number">1</span>){</div><div class="line"> <span class="built_in">printf</span>(<span class="string">“parent ID %d\n”</span>, getpid());</div><div class="line"> sleep(<span class="number">1</span>);</div><div class="line"> }</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> <span class="number">0</span>;</div><div class="line">}</div></pre></td></tr></table></figure>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</div>
</article>
<article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
<div class="post-block">
<link itemprop="mainEntityOfPage" href="http://eregg.com/2016/11/22/C线程/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="name" content="eregg">
<meta itemprop="description" content="">
<meta itemprop="image" content="/uploads/avatar.jpg">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="学不可以已">
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2016/11/22/C线程/" itemprop="url">C线程</a></h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建于" itemprop="dateCreated datePublished" datetime="2016-11-22T09:40:09+08:00">
2016-11-22
</time>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h3 id="线程概念"><a href="#线程概念" class="headerlink" title="线程概念"></a><a href="#线程概念" title="线程概念"></a>线程概念</h3><h4 id="什么是线程"><a href="#什么是线程" class="headerlink" title="什么是线程"></a><a href="#什么是线程" title="什么是线程"></a>什么是线程</h4><h4 id="线程和进程的关系"><a href="#线程和进程的关系" class="headerlink" title="线程和进程的关系"></a><a href="#线程和进程的关系" title="线程和进程的关系"></a>线程和进程的关系</h4><ol>
<li>轻量级进程,也有PCB,创建线程使用的底层函数和创建进程一样,都是clone。</li>
<li>从内核的角度看,进程和线程都是一样的,都有各自不同的PCB,但是PCB中指向内存资源的三级页表是相同的</li>
<li>进程可以蜕变成线程</li>
<li>在美国人眼里,线程就是寄存器和栈</li>
<li><p>在Linux下,线程是最小的执行单位,进程是最小的分配单位</p>
<p><img src="http://123.57.181.198/images/c/cpuscheduling.jpg" alt=" cpu资源调度图"></p>
</li>
</ol>
<h4 id="线程间共享的资源"><a href="#线程间共享的资源" class="headerlink" title="线程间共享的资源"></a><a href="#线程间共享的资源" title="线程间共享的资源"></a>线程间共享的资源</h4><ol>
<li>文件描述符</li>
<li>每种信号的处理方式</li>
<li>当前工作目录</li>
<li>用户ID和组ID</li>
<li><p>内存地址空间</p>
<p><img src="http://123.57.181.198/images/c/pthreadshared.jpg" alt=" 线程共享资源图"></p>
</li>
</ol>
<h4 id="线程间非共享的资源"><a href="#线程间非共享的资源" class="headerlink" title="线程间非共享的资源"></a><a href="#线程间非共享的资源" title="线程间非共享的资源"></a>线程间非共享的资源</h4><ol>
<li>线程ID</li>
<li>处理器现场和栈指针(内核栈)</li>
<li>独立的栈空间(用户空间栈)</li>
<li>errno变量</li>
<li>信号屏蔽字</li>
<li>调度优先级</li>
</ol>
<h4 id="线程优缺点"><a href="#线程优缺点" class="headerlink" title="线程优缺点"></a><a href="#线程优缺点" title="线程优缺点"></a>线程优缺点</h4><ol>
<li>优点</li>
</ol>
<ul>
<li>提高程序的并发性</li>
<li>开销小,不用重新分配内存地址</li>
<li>通信好共享数据方便</li>
</ul>
<ol>
<li>缺点</li>
</ol>
<ul>
<li>线程不稳定(函数库实现)</li>
<li>线程调试比较困难(gdb支持不好)</li>
<li>线程无法使用unix经典事件,例如信号</li>
</ul>
<h3 id="线程原语"><a href="#线程原语" class="headerlink" title="线程原语"></a><a href="#线程原语" title="线程原语"></a>线程原语</h3><h4 id="pthread-create"><a href="#pthread-create" class="headerlink" title="pthread_create"></a><a href="#pthread-create" title="pthread_create"></a>pthread_create</h4><figure class="highlight delphi"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">int pthread_create(pthread_t <em>thread, <span class="keyword">const</span> pthread_attr_t </em>attr,</div><div class="line"> void <em><span class="comment">(</span></em>start_routine) (void <em>), void </em>arg);</div><div class="line">返回值:若成功,返回<span class="number">0</span>;否则,返回错误编号</div></pre></td></tr></table></figure><br>> 当pthread_create成功返回时,新创建线程的线程ID会被设置到thread中,attr参数用来制定各种不同的线程属性。新创建的线程从start_routine函数地址开始运行,该函数只有一个无类型指针参数arg。<br><br>#### <a href="#pthread-self" title="pthread_self"></a>pthread_self<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">pthread_t</span> pthread_self(<span class="keyword">void</span>);</div><div class="line">返回当前线程ID</div></pre></td></tr></table></figure>
<h4 id="pthread-exit"><a href="#pthread-exit" class="headerlink" title="pthread_exit"></a><a href="#pthread-exit" title="pthread_exit"></a>pthread_exit</h4><blockquote>
<p>如果进程中调用了,exit、_Exit、或者_exit,那么整个进程就会终止,与此相类似,如果默认动作是终止进程,那么发送到线程的信号就会终止整个进程。</p>
<p>单个线程可以通过3种方式退出,因此可以在不终止整个进程的情况下,停止它 的控制流。</p>
<ol>
<li>线程有简单的从启动历程中返回,返回值是线程的退出码</li>
<li>线程可以被同一进程的其他线程调用pthread_cancel取消</li>
<li>线程调用pthread_exit<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">pthread_exit</span><span class="params">(<span class="keyword">void</span> *retval)</span></span>;</div></pre></td></tr></table></figure></li>
</ol>
<p>retval 参数是一个无类型指针,与传给启动历程的单个参数类似,进程中的其他线程也可以通过调用pthread_join函数访问到这个指针。</p>
<h4 id="pthread-join"><a href="#pthread-join" class="headerlink" title="pthread_join"></a><a href="#pthread-join" title="pthread_join"></a>pthread_join</h4><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_join</span><span class="params">(<span class="keyword">pthread_t</span> thread, <span class="keyword">void</span> **retval)</span></span>;</div><div class="line">返回值:若成功,返回<span class="number">0</span>,否则返回错误编号</div></pre></td></tr></table></figure>
<p>调用线程将一直阻塞,直到指定的线程调用pthread_exit,从启动例程返回或者被其他线程pthread_cancel取消,如果线程简单地从它的启动例程返回,retval就包含返回码,如果线程是被其他线程pthread_cancel取消的,retval的返回值为-1.</p>
<h4 id="pthread-cancel"><a href="#pthread-cancel" class="headerlink" title="pthread_cancel"></a><a href="#pthread-cancel" title="pthread_cancel"></a>pthread_cancel</h4><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_cancel</span><span class="params">(<span class="keyword">pthread_t</span> thread)</span></span>;</div><div class="line">thread 要被取消的线程ID</div></pre></td></tr></table></figure>
<p>在进程内某个线程可以取消另一个线程。</p>
<h4 id="pthread-detach"><a href="#pthread-detach" class="headerlink" title="pthread_detach"></a><a href="#pthread-detach" title="pthread_detach"></a>pthread_detach</h4><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_detach</span><span class="params">(<span class="keyword">pthread_t</span> thread)</span></span>;</div><div class="line">thread:分离线程ID</div><div class="line">返回值:成功返回<span class="number">0</span>,失败返回错误编号</div></pre></td></tr></table></figure>
<p>一般清空下,线程终止后,其终止状态一直保留到其他线程调用pthread_join获取他的状态为止,但是线程如果设置成分离态pthread_detach的话,线程一旦运行结束系统就立刻回收它占用的所有资源,而不保留终止状态。不能对一个已经处理detach状态的线程调用pthread_join,这样调用将返回EINVAL。如果已经对一个线程调用了pthread_detach就不能再调用pthread_join了。</p>
<h4 id="pthread-equal"><a href="#pthread-equal" class="headerlink" title="pthread_equal"></a><a href="#pthread-equal" title="pthread_equal"></a>pthread_equal</h4><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_equal</span><span class="params">(<span class="keyword">pthread_t</span> t1, <span class="keyword">pthread_t</span> t2)</span></span>;</div></pre></td></tr></table></figure>
<p>比较两个线程是否是同一个</p>
</blockquote>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</div>
</article>
<article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
<div class="post-block">
<link itemprop="mainEntityOfPage" href="http://eregg.com/2016/11/22/多线程同步/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="name" content="eregg">
<meta itemprop="description" content="">
<meta itemprop="image" content="/uploads/avatar.jpg">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="学不可以已">
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2016/11/22/多线程同步/" itemprop="url">多线程同步</a></h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建于" itemprop="dateCreated datePublished" datetime="2016-11-22T09:39:37+08:00">
2016-11-22
</time>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h3 id="线程为什么要同步"><a href="#线程为什么要同步" class="headerlink" title="线程为什么要同步"></a><a href="#线程为什么要同步" title="线程为什么要同步"></a>线程为什么要同步</h3><blockquote>
<p>当多个控制线程共享相同的内存时,需要确保每个线程看到一致的视图,如果每个线程使用的变量都是其他线程不会读取和修改的,那么就不存在一致性问题,同样,如果变量是只读的,多个线程同时读取该变量也不会有一致性问题,但是,<strong>当一个线程可以修改的变量,其他的线程也可以读取或者修改的时候,我们就需要对这些线程进行同步,确保它们在访问变量的存储内容时不会访问到无效的值</strong>。</p>
</blockquote>
<h3 id="互斥量"><a href="#互斥量" class="headerlink" title="互斥量"></a><a href="#互斥量" title="互斥量"></a>互斥量</h3><blockquote>
<p>可以使用pthread的互斥接口来保护数据,确保在同一时间只有一个线程可以访问共享数据,<strong>互斥量(mutex)从本质上说就是一把锁</strong>,在访问共享资源前对互斥量进行设置(加锁),在访问完成后释放(解锁)互斥量,对互斥量进行加锁以后,任何其他试图再次对互斥量进行加锁的线程都会被阻塞直到当前线程释放该互斥锁,如果释放互斥量时有一个以上的线程阻塞,那么所有该锁上的线程都会被变成可运行状态,第一个被运行的线程就可以对互斥量加锁,其他线程就会看到互斥量依然是锁着的,只能回去再次等待它重新变为可用。在这种情况下每次只有一个线程可以向前执行。</p>
</blockquote>
<h4 id="临界区(Critical-Section)"><a href="#临界区(Critical-Section)" class="headerlink" title="临界区(Critical Section)"></a><a href="#临界区(Critical-Section)" title="临界区(Critical Section)"></a>临界区(Critical Section)</h4><blockquote>
<p>保证在某一时刻只有一个线程能访问数据的简便办法。在任意时刻只允许一个线程对共<br>享资源进行访问。如果有多个线程试图同时访问临界区,那么在有一个线程进入后其他所有试图访问此临界区的线程将被挂起,并一直持续到进入临界区的线程离开。临界区在被释放后,其他线程可以继续抢占,并以此达到用原子方式操作共享资源的目的。</p>
</blockquote>
<h4 id="临界区的选定"><a href="#临界区的选定" class="headerlink" title="临界区的选定"></a><a href="#临界区的选定" title="临界区的选定"></a>临界区的选定</h4><blockquote>
<p>临界区的选定因尽可能小,如果选定太大会影响程序的并行处理性能。</p>
</blockquote>
<h4 id="互斥量(mutex)原语"><a href="#互斥量(mutex)原语" class="headerlink" title="互斥量(mutex)原语"></a><a href="#互斥量(mutex)原语" title="互斥量(mutex)原语"></a>互斥量(mutex)原语</h4><h5 id="pthread-mutex-t"><a href="#pthread-mutex-t" class="headerlink" title="pthread_mutex_t"></a><a href="#pthread-mutex-t" title="pthread_mutex_t"></a>pthread_mutex_t</h5><blockquote>
<p><strong>互斥量使用pthread_mutex_t数据类型表示的</strong>。在使用互斥变量以前,必须首先对它进行初始化,<strong>_可以把他设置为常量PTHREAD_MUTEX<em>INITIALIZER(只适用于静态分配的互斥量)</em></strong>,也可以<strong>通过调用pthread_mutex_init函数进行初始化</strong>。如果动态分配互斥量(例如,通过调malloc函数),在释放内存前需要调用pthread_mutex_destroy。</p>
<h5 id="pthread-mutex-init"><a href="#pthread-mutex-init" class="headerlink" title="pthread_mutex_init"></a><a href="#pthread-mutex-init" title="pthread_mutex_init"></a>pthread_mutex_init</h5><figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_mutex_init</span><span class="params">(<span class="keyword">pthread_mutex_t</span> <em><span class="keyword">restrict</span> mutex,</em></span></span></div><div class="line"> <span class="keyword">const</span> <span class="keyword">pthread_mutexattr_t</span> <span class="keyword">restrict</span> attr);</div><div class="line"><span class="keyword">pthread_mutex_t</span> mutex = PTHREAD_MUTEX_INITIALIZER;</div><div class="line">返回值:成功返回<span class="number">0</span>,否则,返回错误编号。</div></pre></td></tr></table></figure>
<p>需要默认的属性初始化互斥量,只需要把attr设为NULL。</p>
</blockquote>
<h5 id="pthread-mutex-lock"><a href="#pthread-mutex-lock" class="headerlink" title="pthread_mutex_lock"></a><a href="#pthread-mutex-lock" title="pthread_mutex_lock"></a>pthread_mutex_lock</h5><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_mutex_lock</span><span class="params">(<span class="keyword">pthread_mutex_t</span> <em>mutex)</em></span></span>;</div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_mutex_trylock</span><span class="params">(<span class="keyword">pthread_mutex_t</span> mutex)</span></span>;</div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_mutex_unlock</span><span class="params">(<span class="keyword">pthread_mutex_t</span> <em>mutex)</em></span></span>;</div><div class="line">返回值:成功返回<span class="number">0</span>,否则,返回错误编号。</div></pre></td></tr></table></figure><br>> 对互斥量进行加锁,需要调用pthread_mutex_lock。如果互斥量已经上锁,调用线程将阻塞直到互斥量被解锁,对互斥量解锁,需要调用pthread_mutex_unlock。<br>><br>> ##### <a href="#pthread-mutex-unlock" title="pthread_mutex_unlock"></a>pthread_mutex_unlock<br>><br>> ##### <a href="#pthread-mutex-destroy" title="pthread_mutex_destroy"></a>pthread_mutex<em>destroy<br><br>### <a href="#死锁" title="死锁"></a>死锁<br>> 如果一个线程试图对同一个互斥量加锁两次,那么他自身就会陷入一种死锁状态,但是使用互斥量时还有其他不太明显的方式也会产生死锁。例如,程序中有一个以上的互斥量时,如果一个线程在持有第一个互斥量时,并且试图锁住第二个互斥量时处于阻塞状态,<br>> (此时第一个互斥量也一直被持有),此时第二个持有第二个互斥量的线程,也在试图获取第一个互斥量时,死锁就产生了,因为两个线程都在互相请求另一个线程拥有的资源,所以这两个线程都无法前进,于是就产生死锁。<br><br>### <a href="#读写锁" title="读写锁"></a>读写锁<br>> 读写锁(reader-writer lock)与互斥量类似,不过读写锁允许更高的并发性,**</em>读共享,写独占_**<br><br>#### <a href="#读写锁原语" title="读写锁原语"></a>读写锁原语<br><br>##### <a href="#pthread-rwlock-t" title="pthread_rwlock_t"></a>pthread_rwlock_t<br>> 读写锁类型<br><br>##### <a href="#pthread-rwlock-init" title="pthread_rwlock_init"></a>pthread_rwlock_init<br><br>##### <a href="#pthread-rwlock-destroy" title="pthread_rwlock_destroy"></a>pthread_rwlock_destroy<br><figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_rwlock_init</span><span class="params">(<span class="keyword">pthread_rwlock_t</span> <span class="keyword">restrict</span> rwlock,</span></span></div><div class="line"> <span class="keyword">const</span> <span class="keyword">pthread_rwlockattr_t</span> <em><span class="keyword">restrict</span> attr);</em></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_rwlock_destroy</span><span class="params">(<span class="keyword">pthread_rwlock_t</span> rwlock)</span></span>;</div><div class="line">两个函数返回值:若成功,返回<span class="number">0</span>;否则,返回错误编号</div></pre></td></tr></table></figure><br>> 读写锁通过调用<strong>_pthread_rwlock<em>init</em></strong>进行初始化,如果希望读写锁有默认属性,可以传一个NULL指针给attr<br>><br>> 在释放读写锁占用的内存之前,需要调用<strong>_pthread_rwlock<em>destroy</em></strong>做清理工作, 如果<strong>_pthread_rwlock<em>init</em></strong>为读写锁分配了资源,<strong>_pthread_rwlock<em>destroy</em></strong>将释放这些资源。<br><br>##### <a href="#pthread-rwlock-rdlock" title="pthread_rwlock_rdlock"></a>pthread_rwlock_rdlock<br><br>##### <a href="#pthread-rwlock-wrlock" title="pthread_rwlock_wrlock"></a>pthread_rwlock_wrlock<br><br>##### <a href="#pthread-rwlock-tryrdlock" title="pthread_rwlock_tryrdlock"></a>pthread_rwlock_tryrdlock<br><br>##### <a href="#pthread-rwlock-trywrlock" title="pthread_rwlock_trywrlock"></a>pthread_rwlock_trywrlock<br><br>##### <a href="#pthread-rwlock-unlock" title="pthread_rwlock_unlock"></a>pthread_rwlock_unlock<br><figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_rwlock_rdlock</span><span class="params">(<span class="keyword">pthread_rwlock_t</span> <em>rwlock)</em></span></span>;</div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_rwlock_wrlock</span><span class="params">(<span class="keyword">pthread_rwlock_t</span> rwlock)</span></span>;</div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_rwlock_tryrdlock</span><span class="params">(<span class="keyword">pthread_rwlock_t</span> <em>rwlock)</em></span></span>;</div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_rwlock_trywrlock</span><span class="params">(<span class="keyword">pthread_rwlock_t</span> rwlock)</span></span>;</div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_rwlock_unlock</span><span class="params">(<span class="keyword">pthread_rwlock_t</span> <em>rwlock)</em></span></span>;</div><div class="line">所有函数返回值:若成功,返回<span class="number">0</span>;否则,返回错误编号</div></pre></td></tr></table></figure><br>> 要在读模式下锁定读写锁,需要调用<strong>_pthread_rwlock<em>rdlock</em></strong>。要在模式下锁定读写锁,需要调用<strong>_pthread_rwlock<em>wrlock</em></strong>。不管以何种方式锁定读写锁,都可以调用<strong>_pthread_rwlock<em>unlock</em></strong>进行解锁。<br>><br>> <strong>_pthread_rwlock_tryrdlock,pthread_rwlock<em>trywrlock</em></strong>,非阻塞获得锁<br><br>### <a href="#条件变量" title="条件变量"></a>条件变量
互斥量的存在问题:<br> 互斥量是线程程序必需的工具,但它们并非万能的。例如,<strong><em>如果线程正在等待共享数据内某个条件出现,那会发生什么呢?它可以重复对互斥对象锁定和解锁,每次都会检查共享数据结构,以查找某个值。但这是在浪费时间和资源,而且这种繁忙查询的效率非常低</em></strong>。<br> 在每次检查之间,可以让调用线程短暂地进入睡眠,比如睡眠三秒钟,但是因此线程代码就无法最快作出响应。真正需要的是这样一种方法:当线程在等待满足某些条件时使线程进入睡眠状态。一旦条件满足,就唤醒因等待满足特定条件而睡眠的线程。如果能够做到这一点,线程代码将是非常高效的,并且不会占用宝贵的互斥对象锁。这正是 POSIX 条件变量能做的事!<br><br><em> 条件变量:<br> 条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足,它常和互斥锁一起使用。使用时,<strong><em>条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化。一旦其它的某个线程改变了条件变量,它将通知相应的条件变量唤醒一个或多个正被此条件变量阻塞的线程。这些线程将重新锁定互斥锁并重新测试条件是否满足</em></strong>。
</em> 条件变量是线程可用的另一种同步机制,条件变量给多线程提供了一个会和的场所,<strong><em>条件变量与互斥量一起使用时,允许线程以无竞争的方式等待特定条件的发生</em></strong>。<br><br>#### <a href="#条件变量原语" title="条件变量原语"></a>条件变量原语<br><br>##### <a href="#pthread-cond-t" title="pthread_cond_t"></a>pthread_cond_t<br>> 条件变量类型<br><br>##### <a href="#pthread-cond-init" title="pthread_cond_init"></a>pthread_cond_init<br><br>##### <a href="#pthread-cond-destroy" title="pthread_cond_destroy"></a>pthread_cond_destroy<br><figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">pthread_cond_t</span> cond = PTHREAD_COND_INITIALIZER; <span class="comment">//静态初始化</span></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_cond_init</span><span class="params">(<span class="keyword">pthread_cond_t</span> <em><span class="keyword">restrict</span> cond,</em></span></span></div><div class="line"> <span class="keyword">const</span> <span class="keyword">pthread_condattr_t</span> <span class="keyword">restrict</span> attr);</div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_cond_destroy</span><span class="params">(<span class="keyword">pthread_cond_t</span> <em>cond)</em></span></span>;</div><div class="line">两个函数返回值:若成功,返回<span class="number">0</span>;否则,返回错误编号</div></pre></td></tr></table></figure><br>> 在使用条件变量之前,必须先对它进行初始化。由pthread_cond_t数据类型表示的条件变量可以用两种方式进行初始化,可以把常量PTHREAD_COND_INITIALIZER赋给静态分配的条件变量,但是如果条件变量是动态分配的就需要使用pthread_cond_init函数来对它进行初始化。在释放条件变量底层的内存空间之前,可以使用pthread_cond_destroy函数对条件变量进行反初始化。<br><br>##### <a href="#pthread-cond-wait" title="pthread_cond_wait"></a>pthread_cond_wait<br><br>##### <a href="#pthread-cond-timedwait" title="pthread_cond_timedwait"></a>pthread_cond_timedwait<br><figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_cond_wait</span><span class="params">(<span class="keyword">pthread_cond_t</span> <span class="keyword">restrict</span> cond,</span></span></div><div class="line"> <span class="keyword">pthread_mutex_t</span> <em><span class="keyword">restrict</span> mutex);</em></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_cond_timedwait</span><span class="params">(<span class="keyword">pthread_cond_t</span> <span class="keyword">restrict</span> cond,</span></span></div><div class="line"> <span class="keyword">pthread_mutex_t</span> <em><span class="keyword">restrict</span> mutex,</em></div><div class="line"> <span class="keyword">const</span> <span class="keyword">struct</span> timespec <span class="keyword">restrict</span> abstime);</div><div class="line">两个函数返回值:若成功,返回<span class="number">0</span>;否则,返回错误编号</div></pre></td></tr></table></figure><br>> 传递给pthread_cond<em>wait的互斥量对条件进行保护。**</em>调用者把锁住的互斥量传给函数,函数然后自动把调用线程放到等待条件的线程列表上,对互斥量解锁。这就关闭了条件检查和线程进入睡眠状态等待条件改变这两个操作之间的时间同道,这样线程就不会错过条件的任何变化,pthread_cond<em>wait返回时,互斥量再次被锁住</em><strong>。<br>><br>> pthread_cond_timedwait函数与pthread_cond_wait函数类似,只是多了一个超时,它是通过timespec结构指定的。<br><br>##### <a href="#pthread-cond-signal" title="pthread_cond_signal"></a>pthread_cond_signal<br><br>##### <a href="#pthread-cond-broadcast" title="pthread_cond_broadcast"></a>pthread_cond_broadcast<br><figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_cond_signal</span><span class="params">(<span class="keyword">pthread_cond_t</span> <em>cond)</em></span></span>;</div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_cond_broadcast</span><span class="params">(<span class="keyword">pthread_cond_t</span> cond)</span></span>;</div><div class="line">两个函数返回值:若成功,返回<span class="number">0</span>;否则,返回错误编号</div></pre></td></tr></table></figure><br>> </strong>_pthread_cond_signal函数至少能唤醒一个等待该条件的线程,pthread_cond<em>broadcast函数则能唤醒等待该条件的所有线程。</em><em>*<br>> 在调用pthread_cond_signal或者pthread_cond_broadcast时,我们说这是在给线程或者条件发信号,必须注意,一定要在改变条件状态以后再给线程发信号。<br><br>### <a href="#信号量" title="信号量"></a>信号量<br><br>### <a href="#进程间锁" title="进程间锁"></a>进程间锁<br><br>### <a href="#实例一(互斥量锁)" title="实例一(互斥量锁)"></a>实例一(互斥量锁)<br><figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdio.h></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdlib.h></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><unistd.h></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><pthread.h></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">define</span> NLOOP 5000</span></div><div class="line"><span class="comment">//定义锁</span></div><div class="line"><span class="keyword">pthread_mutex_t</span> lock;</div><div class="line"></div><div class="line"><span class="keyword">int</span> counter;</div><div class="line"><span class="function"><span class="keyword">void</span></span></div></pre></td></tr></table></figure></em> <span class="title">doit</span><span class="params">(<span class="keyword">void</span> *argv)</span>{<div class="line"> <span class="keyword">int</span> i, val;</div><div class="line"> <span class="keyword">for</span>(i = <span class="number">0</span>; i < NLOOP; i++){</div><div class="line"> <span class="comment">//获取互斥锁,如果锁被其他线程持有,则阻塞等待。</span></div><div class="line"> pthread_mutex_lock(&lock);</div><div class="line"> val = counter;</div><div class="line"> <span class="built_in">printf</span>(<span class="string">“%x: %d\n”</span>, pthread_self(), val+<span class="number">1</span>);</div><div class="line"> counter = val+<span class="number">1</span>;</div><div class="line"> <span class="comment">//释放互斥锁,以便其他线程持有</span></div><div class="line"> pthread_mutex_unlock(&lock);</div><div class="line"> } </div><div class="line"> <span class="keyword">return</span> <span class="literal">NULL</span>;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span>{</div><div class="line"> <span class="comment">//初始化互斥锁</span></div><div class="line"> pthread_mutex_init(&lock, <span class="literal">NULL</span>);</div><div class="line"> <span class="keyword">pthread_t</span> tidA, tidB;</div><div class="line"> pthread_create(&tidA, <span class="literal">NULL</span>, &doit, <span class="literal">NULL</span>);</div><div class="line"> pthread_create(&tidB, <span class="literal">NULL</span>, &doit, <span class="literal">NULL</span>);</div><div class="line"></div><div class="line"> pthread_join(tidA, <span class="literal">NULL</span>);</div><div class="line"> pthread_join(tidB, <span class="literal">NULL</span>);</div><div class="line"> <span class="comment">//销毁锁</span></div><div class="line"> pthread_mutex_destroy(&lock);</div><div class="line"></div><div class="line"> <span class="keyword">return</span> <span class="number">0</span>;</div><div class="line">}</div>
<h3 id="实例二(死锁)"><a href="#实例二(死锁)" class="headerlink" title="实例二(死锁)"></a><a href="#实例二(死锁)" title="实例二(死锁)"></a>实例二(死锁)</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdio.h></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdlib.h></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><unistd.h></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><pthread.h></span></span></div><div class="line"></div><div class="line"><span class="comment">//定义两个互斥量锁</span></div><div class="line"><span class="keyword">pthread_mutex_t</span> lockA;</div><div class="line"><span class="keyword">pthread_mutex_t</span> lockB;</div><div class="line"></div><div class="line"><span class="keyword">int</span> a, b;</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">void</span><em> <span class="title">pthread_fun1</span><span class="params">(<span class="keyword">void</span></span></em> argv)</span>{</div><div class="line"> <span class="keyword">while</span>(<span class="number">1</span>){</div><div class="line"> <span class="comment">//获取锁A</span></div><div class="line"> <span class="built_in">printf</span>(<span class="string">“获取lockA\n”</span>);</div><div class="line"> pthread_mutex_lock(&lockA);</div><div class="line"> a++;</div><div class="line"> <span class="comment">//获取锁B</span></div><div class="line"> <span class="built_in">printf</span>(<span class="string">“获取lockB\n”</span>);</div><div class="line"> pthread_mutex_lock(&lockB);</div><div class="line"> b++;</div><div class="line"> <span class="comment">//释放锁B</span></div><div class="line"> pthread_mutex_unlock(&lockB);</div><div class="line"> <span class="comment">//释放锁A</span></div><div class="line"> pthread_mutex_unlock(&lockA);</div><div class="line"> <span class="built_in">printf</span>(<span class="string">“%x a=%d b=%d\n”</span>, pthread_self(), a, b); </div><div class="line"> } </div><div class="line"></div><div class="line"> <span class="keyword">return</span> <span class="literal">NULL</span>;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">void</span><em> <span class="title">pthread_fun2</span><span class="params">(<span class="keyword">void</span></span></em> argv)</span>{</div><div class="line"> <span class="keyword">while</span>(<span class="number">1</span>){</div><div class="line"> <span class="comment">//获取锁B</span></div><div class="line"> <span class="built_in">printf</span>(<span class="string">“获取lockB\n”</span>);</div><div class="line"> pthread_mutex_lock(&lockB);</div><div class="line"> a++;</div><div class="line"> <span class="comment">//获取锁A</span></div><div class="line"> <span class="built_in">printf</span>(<span class="string">“获取lockA\n”</span>);</div><div class="line"> pthread_mutex_lock(&lockA);</div><div class="line"> b++;</div><div class="line"> <span class="comment">//释放锁A</span></div><div class="line"> pthread_mutex_unlock(&lockA);</div><div class="line"> <span class="comment">//释放锁B</span></div><div class="line"> pthread_mutex_unlock(&lockB);</div><div class="line"> <span class="built_in">printf</span>(<span class="string">“%x a=%d b=%d\n”</span>, pthread_self(), a, b);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> <span class="literal">NULL</span>;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">(<span class="keyword">void</span>)</span></span>{</div><div class="line"></div><div class="line"> <span class="comment">//初始化锁</span></div><div class="line"> pthread_mutex_init(&lockA, <span class="literal">NULL</span>);</div><div class="line"> pthread_mutex_init(&lockB, <span class="literal">NULL</span>);</div><div class="line"></div><div class="line"> <span class="keyword">pthread_t</span> tidA, tidB;</div><div class="line"></div><div class="line"> pthread_create(&tidA, <span class="literal">NULL</span>, &pthread_fun1, <span class="literal">NULL</span>);</div><div class="line"> pthread_create(&tidB, <span class="literal">NULL</span>, &pthread_fun2, <span class="literal">NULL</span>);</div><div class="line"></div><div class="line"> pthread_join(tidA, <span class="literal">NULL</span>);</div><div class="line"> pthread_join(tidB, <span class="literal">NULL</span>);</div><div class="line"></div><div class="line"> <span class="keyword">return</span> <span class="number">0</span>;</div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="实例三(读写锁)"><a href="#实例三(读写锁)" class="headerlink" title="实例三(读写锁)"></a><a href="#实例三(读写锁)" title="实例三(读写锁)"></a>实例三(读写锁)</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdio.h></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdlib.h></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><unistd.h></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><pthread.h></span></span></div><div class="line"></div><div class="line"><span class="comment">//定义一个全局计数器</span></div><div class="line"><span class="keyword">int</span> counter;</div><div class="line"><span class="comment">//创建一个读写锁</span></div><div class="line"><span class="keyword">pthread_rwlock_t</span> rwlock;</div><div class="line"></div><div class="line"><span class="comment">//3个写线程,不定时写同一全局资源</span></div><div class="line"><span class="function"><span class="keyword">void</span><em> <span class="title">th_write</span><span class="params">(<span class="keyword">void</span> </span></em> argv)</span>{</div><div class="line"> <span class="keyword">int</span> t;</div><div class="line"> <span class="keyword">while</span>(<span class="number">1</span>){</div><div class="line"> usleep(<span class="number">100</span>);</div><div class="line"> pthread_rwlock_wrlock(&rwlock);</div><div class="line"> t = counter;</div><div class="line"> usleep(<span class="number">100</span>);</div><div class="line"> <span class="built_in">printf</span>(<span class="string">“write %x counter=%d ++counter=%d\n”</span>, pthread_self(), t, ++counter);</div><div class="line"> pthread_rwlock_unlock(&rwlock);</div><div class="line"> usleep(<span class="number">100</span>);</div><div class="line"> }</div><div class="line"></div><div class="line">}</div><div class="line"></div><div class="line"><span class="comment">//5个读线程,不定时读同一全局资源</span></div><div class="line"><span class="function"><span class="keyword">void</span><em> <span class="title">th_read</span><span class="params">(<span class="keyword">void</span> </span></em> argv)</span>{</div><div class="line"></div><div class="line"> <span class="keyword">while</span>(<span class="number">1</span>){</div><div class="line"> pthread_rwlock_rdlock(&rwlock);</div><div class="line"> <span class="built_in">printf</span>(<span class="string">“read %x counter=%d\n”</span>, pthread_self(), counter);</div><div class="line"> pthread_rwlock_unlock(&rwlock);</div><div class="line"> usleep(<span class="number">100</span>);</div><div class="line"> }</div><div class="line"></div><div class="line">}</div><div class="line"></div><div class="line"><span class="comment">//创建3个写线程,5个读线程</span></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span>{</div><div class="line"> <span class="keyword">pthread_t</span> tid[<span class="number">8</span>];</div><div class="line"> <span class="comment">//初始化读写锁</span></div><div class="line"> pthread_rwlock_init(&rwlock, <span class="literal">NULL</span>);</div><div class="line"> <span class="keyword">int</span> i;</div><div class="line"> <span class="comment">//创建3个写线程</span></div><div class="line"> <span class="keyword">for</span>(i = <span class="number">0</span>; i < <span class="number">3</span>; i++){</div><div class="line"> pthread_create(&tid[i], <span class="literal">NULL</span>, th_write, <span class="literal">NULL</span>);</div><div class="line"> }</div><div class="line"> <span class="comment">//创建5个读线程</span></div><div class="line"> <span class="keyword">for</span>(i = <span class="number">0</span>; i < <span class="number">5</span>; i++){</div><div class="line"> pthread_create(&tid[i+<span class="number">3</span>], <span class="literal">NULL</span>, th_read, <span class="literal">NULL</span>);</div><div class="line"> }</div><div class="line"> <span class="comment">//销毁读写锁</span></div><div class="line"> pthread_rwlock_destroy(&rwlock);</div><div class="line"></div><div class="line"> <span class="comment">//回收线程资源</span></div><div class="line"> <span class="keyword">for</span>(i = <span class="number">0</span>; i < <span class="number">8</span>; i++){</div><div class="line"> pthread_join(tid[i], <span class="literal">NULL</span>);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> <span class="number">0</span>;</div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="实例四(条件变量)"><a href="#实例四(条件变量)" class="headerlink" title="实例四(条件变量)"></a><a href="#实例四(条件变量)" title="实例四(条件变量)"></a>实例四(条件变量)</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div><div class="line">82</div><div class="line">83</div><div class="line">84</div><div class="line">85</div><div class="line">86</div><div class="line">87</div><div class="line">88</div><div class="line">89</div><div class="line">90</div><div class="line">91</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdio.h></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdlib.h></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><unistd.h></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><pthread.h></span></span></div><div class="line"></div><div class="line"><span class="comment">//定义一个互斥锁</span></div><div class="line"><span class="keyword">pthread_mutex_t</span> lock;</div><div class="line"><span class="comment">//定义一个条件变量</span></div><div class="line"><span class="keyword">pthread_cond_t</span> cond;</div><div class="line"></div><div class="line"><span class="comment">//定义一个链表结构体(多线程操作的全局资源)</span></div><div class="line"><span class="keyword">struct</span> msg{</div><div class="line"> <span class="keyword">struct</span> msg<em> next; <span class="comment">//指针域</span></em></div><div class="line"> <span class="keyword">int</span> num; <span class="comment">//数据域</span></div><div class="line">};</div><div class="line"></div><div class="line"><span class="comment">//链表头</span></div><div class="line"><span class="keyword">struct</span> msg head;</div><div class="line"></div><div class="line"><span class="comment">//生产者</span></div><div class="line"><span class="function"><span class="keyword">void</span><em> <span class="title">producer</span><span class="params">(<span class="keyword">void</span></span></em> argv)</span>{</div><div class="line"> <span class="keyword">while</span>(<span class="number">1</span>){</div><div class="line"> <span class="comment">//获取锁</span></div><div class="line"> pthread_mutex_lock(&lock);</div><div class="line"></div><div class="line"> <span class="comment">//生产商品 (此处部分代码可放在获取锁之前执行,进行优化。为了看着直观所以代码都写在临界区了)</span></div><div class="line"> <span class="keyword">struct</span> msg <em>mp = <span class="built_in">malloc</span>(<span class="keyword">sizeof</span>(<span class="keyword">struct</span> msg));</em></div><div class="line"> mp->next = head;</div><div class="line"> mp->num = rand() % <span class="number">1000</span> + <span class="number">1</span>;</div><div class="line"> head = mp;</div><div class="line"> <span class="built_in">printf</span>(<span class="string">“Produce %d\n”</span>, mp->num);</div><div class="line"></div><div class="line"> <span class="comment">//释放锁</span></div><div class="line"> pthread_mutex_unlock(&lock);</div><div class="line"></div><div class="line"> <span class="comment">//通知其中一个线程(停留在pthread_cond_wait的线程)</span></div><div class="line"> pthread_cond_signal(&cond);</div><div class="line"></div><div class="line"> <span class="comment">//随机停留几秒,方便观察</span></div><div class="line"> sleep(rand() % <span class="number">3</span>);</div><div class="line"> }</div><div class="line">}</div><div class="line"></div><div class="line"><span class="comment">//消费者</span></div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">consumer</span><span class="params">(<span class="keyword">void</span><em> argv)</em></span></span>{</div><div class="line"> <span class="keyword">while</span>(<span class="number">1</span>){</div><div class="line"> <span class="comment">//获取锁</span></div><div class="line"> pthread_mutex_lock(&lock);</div><div class="line"> <span class="keyword">while</span>(head == <span class="literal">NULL</span>){</div><div class="line"> <span class="comment">//等待条件成立</span></div><div class="line"> pthread_cond_wait(&cond, &lock);</div><div class="line"> <span class="built_in">printf</span>(<span class="string">“pthread_cond_wait\n”</span>);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">//消费产品</span></div><div class="line"> <span class="keyword">struct</span> msg mp = head;</div><div class="line"> head = mp->next;</div><div class="line"> <span class="built_in">printf</span>(<span class="string">“Consume %d\n”</span>, mp->num);</div><div class="line"> <span class="built_in">free</span>(mp);</div><div class="line"></div><div class="line"> <span class="comment">//释放锁</span></div><div class="line"> pthread_mutex_unlock(&lock);</div><div class="line"> sleep(rand() % <span class="number">3</span>);</div><div class="line"> }</div><div class="line">}</div><div class="line"></div><div class="line"><span class="comment">//使用条件变量(thread_cond_t)实现生产者消费者模型</span></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span>{</div><div class="line"></div><div class="line"> <span class="comment">//初始化互斥锁</span></div><div class="line"> pthread_mutex_init(&lock, <span class="literal">NULL</span>);</div><div class="line"> <span class="comment">//初始化条件变量</span></div><div class="line"> pthread_cond_init(&cond, <span class="literal">NULL</span>);</div><div class="line"></div><div class="line"> <span class="keyword">pthread_t</span> pid, cid;</div><div class="line"> <span class="comment">//创建生产者线程</span></div><div class="line"> pthread_create(&pid, <span class="literal">NULL</span>, producer, <span class="literal">NULL</span>);</div><div class="line"> <span class="comment">//创建消费者线程</span></div><div class="line"> pthread_create(&cid, <span class="literal">NULL</span>, consumer, <span class="literal">NULL</span>);</div><div class="line"></div><div class="line"> <span class="comment">//回收线程</span></div><div class="line"> pthread_join(pid, <span class="literal">NULL</span>);</div><div class="line"> pthread_join(cid, <span class="literal">NULL</span>);</div><div class="line"></div><div class="line"> <span class="comment">//销毁锁</span></div><div class="line"> pthread_mutex_destroy(&lock);</div><div class="line"> <span class="comment">//销毁条件变量</span></div><div class="line"> pthread_cond_destroy(&cond);</div><div class="line"></div><div class="line"> <span class="keyword">return</span> <span class="number">0</span>;</div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="实例五(信号量)"><a href="#实例五(信号量)" class="headerlink" title="实例五(信号量)"></a><a href="#实例五(信号量)" title="实例五(信号量)"></a>实例五(信号量)</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdio.h></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdlib.h></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><unistd.h></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><pthread.h></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><semaphore.h></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">define</span> NUM 5</span></div><div class="line"></div><div class="line"><span class="comment">//全局资源</span></div><div class="line"><span class="keyword">int</span> <span class="built_in">queue</span>[NUM];</div><div class="line"><span class="comment">//定义两个信号量</span></div><div class="line"><span class="comment">//blank_number 表示队列空闲数量</span></div><div class="line"><span class="comment">//product_number 表示队列使用数量</span></div><div class="line"><span class="keyword">sem_t</span> blank_number, product_number;</div><div class="line"></div><div class="line"><span class="comment">//生产者</span></div><div class="line"><span class="function"><span class="keyword">void</span><em> <span class="title">producer</span><span class="params">(<span class="keyword">void</span></span></em> argv)</span>{</div><div class="line"> <span class="keyword">int</span> i = <span class="number">0</span>;</div><div class="line"> <span class="keyword">while</span>(<span class="number">1</span>){</div><div class="line"> </div><div class="line"> <span class="comment">//如果blank_number为0,阻塞等待,调用成功后,blank_number-1</span></div><div class="line"> sem_wait(&blank_number);</div><div class="line"> <span class="built_in">queue</span>[i] = rand() % <span class="number">1000</span> + <span class="number">1</span>;<span class="comment">//生产商品</span></div><div class="line"> <span class="built_in">printf</span>(<span class="string">“produce %d\n”</span>, <span class="built_in">queue</span>[i]);</div><div class="line"> <span class="comment">//调用成功后,product_number+1,表示仓库生产了一件商品,product_number>0 消费者开始消费产品。</span></div><div class="line"> sem_post(&product_number);</div><div class="line"> i = (i + <span class="number">1</span>) % NUM;</div><div class="line"></div><div class="line"> <span class="comment">//usleep(rand() % 3000);</span></div><div class="line"> } </div><div class="line">}</div><div class="line"></div><div class="line"><span class="comment">//消费者</span></div><div class="line"><span class="function"><span class="keyword">void</span><em> <span class="title">consumer</span><span class="params">(<span class="keyword">void</span></span></em> argv)</span>{</div><div class="line"> <span class="keyword">int</span> i = <span class="number">0</span>;</div><div class="line"> <span class="keyword">while</span>(<span class="number">1</span>){</div><div class="line"> <span class="comment">//如果product_number为0,阻塞等待,调用成功后,product_number-1</span></div><div class="line"> sem_wait(&product_number);</div><div class="line"> <span class="comment">//消费产品</span></div><div class="line"> <span class="built_in">printf</span>(<span class="string">“Consume %d\n”</span>, <span class="built_in">queue</span>[i]);</div><div class="line"> <span class="built_in">queue</span>[i] = <span class="number">0</span>;</div><div class="line"> <span class="comment">//调用成功后,blank_number+1,表示仓库消费了一件商品,blank_number>0 生成这开始生产产品</span></div><div class="line"> sem_post(&blank_number);</div><div class="line"> i = (i + <span class="number">1</span>) % NUM;</div><div class="line"></div><div class="line"> sleep(rand()%<span class="number">5</span>);</div><div class="line"> }</div><div class="line">}</div><div class="line"></div><div class="line"><span class="comment">//使用信号量同步线程</span></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span>{</div><div class="line"></div><div class="line"> <span class="keyword">pthread_t</span> pid, cid;</div><div class="line"></div><div class="line"> <span class="comment">//初始化信号量</span></div><div class="line"> sem_init(&blank_number, <span class="number">0</span>, NUM);</div><div class="line"> sem_init(&product_number, <span class="number">0</span>, <span class="number">0</span>);</div><div class="line"></div><div class="line"> <span class="comment">//创建线程</span></div><div class="line"> pthread_create(&pid, <span class="literal">NULL</span>, producer, <span class="literal">NULL</span>);</div><div class="line"> pthread_create(&cid, <span class="literal">NULL</span>, consumer, <span class="literal">NULL</span>);</div><div class="line"></div><div class="line"> <span class="comment">//回收线程资源</span></div><div class="line"> pthread_join(pid, <span class="literal">NULL</span>);</div><div class="line"> pthread_join(cid, <span class="literal">NULL</span>);</div><div class="line"></div><div class="line"> <span class="comment">//销毁信号量</span></div><div class="line"> sem_destroy(&blank_number);</div><div class="line"> sem_destroy(&product_number);</div><div class="line"></div><div class="line"> <span class="keyword">return</span> <span class="number">0</span>;</div><div class="line">}</div></pre></td></tr></table></figure>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</div>
</article>
<article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
<div class="post-block">
<link itemprop="mainEntityOfPage" href="http://eregg.com/2016/11/22/nginx反向代理与负载均衡/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="name" content="eregg">
<meta itemprop="description" content="">
<meta itemprop="image" content="/uploads/avatar.jpg">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="学不可以已">
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2016/11/22/nginx反向代理与负载均衡/" itemprop="url">nginx反向代理与负载均衡</a></h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建于" itemprop="dateCreated datePublished" datetime="2016-11-22T09:39:10+08:00">
2016-11-22
</time>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h3 id="什么是反向代理"><a href="#什么是反向代理" class="headerlink" title="什么是反向代理"></a><a href="#什么是反向代理" title="什么是反向代理"></a>什么是反向代理</h3><p>反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个服务器。<br><img src="http://123.57.181.198/images/linux/reverseproxy.jpg" alt="反向代理"></p>
<h3 id="什么是负载均衡"><a href="#什么是负载均衡" class="headerlink" title="什么是负载均衡"></a><a href="#什么是负载均衡" title="什么是负载均衡"></a>什么是负载均衡</h3><p>负载均衡,英文名称为Load Balance,是指建立在现有网络结构之上,并提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。其原理就是数据流量分摊到多个服务器上执行,减轻每台服务器的压力,多台服务器共同完成工作任务,从而提高了数据的吞吐量。<br><img src="http://123.57.181.198/images/linux/loadbalance.jpg" alt="负载均衡"></p>
<h3 id="Nginx的安装"><a href="#Nginx的安装" class="headerlink" title="Nginx的安装"></a><a href="#Nginx的安装" title="Nginx的安装"></a>Nginx的安装</h3><h4 id="下载nginx"><a href="#下载nginx" class="headerlink" title="下载nginx"></a><a href="#下载nginx" title="下载nginx"></a>下载nginx</h4><p>官网:<a href="http://nginx.org/" target="_blank" rel="external">http://nginx.org/</a></p>
<h4 id="上传并解压nginx"><a href="#上传并解压nginx" class="headerlink" title="上传并解压nginx"></a><a href="#上传并解压nginx" title="上传并解压nginx"></a>上传并解压nginx</h4><figure class="highlight sh"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">tar -zxvf nginx-1.8.1.tar.gz -C /usr/<span class="built_in">local</span>/src</div></pre></td></tr></table></figure>
<h4 id="编译nginx"><a href="#编译nginx" class="headerlink" title="编译nginx"></a><a href="#编译nginx" title="编译nginx"></a>编译nginx</h4><p>#进入到nginx源码目录</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="built_in">cd</span> /usr/<span class="built_in">local</span>/src nginx-1.8.1</div></pre></td></tr></table></figure>
<p>#检查安装环境</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">./configure –prefix=/usr/<span class="built_in">local</span>/nginx</div></pre></td></tr></table></figure>
<p>#缺包报错 ./configure: error: C compiler cc is not found</p>
<p>#使用YUM安装缺少的包</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">yum -y install gcc pcre-devel openssl openssl-devel</div></pre></td></tr></table></figure>
<p>#编译安装</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">make && make install</div></pre></td></tr></table></figure>
<h3 id="配置nginx"><a href="#配置nginx" class="headerlink" title="配置nginx"></a><a href="#配置nginx" title="配置nginx"></a>配置nginx</h3><h4 id="配置反向代理"><a href="#配置反向代理" class="headerlink" title="配置反向代理"></a><a href="#配置反向代理" title="配置反向代理"></a>配置反向代理</h4><p>修改nginx配置文件</p>
<figure class="highlight crmsh"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">server {</div><div class="line"> listen <span class="number">80</span>;</div><div class="line"> server_namenx-<span class="number">01</span>.itcast.cn;</div><div class="line"> <span class="keyword">location</span> <span class="title">/ {</span></div><div class="line"> root html;</div><div class="line"> proxy_pass http://<span class="number">192.168</span>.<span class="number">0.21</span>:<span class="number">8080</span>;</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<h4 id="配置负载均衡"><a href="#配置负载均衡" class="headerlink" title="配置负载均衡"></a><a href="#配置负载均衡" title="配置负载均衡"></a>配置负载均衡</h4><p>在http这个节下面配置一个叫upstream的,后面的名字可以随意取,但是要和location下的proxy_pass <a href="http://后的保持一致。" target="_blank" rel="external">http://后的保持一致。</a></p>
<figure class="highlight nginx"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"><span class="section">http</span> {</div><div class="line"> <span class="attribute">upstream</span> tomcats { </div><div class="line"> <span class="attribute">server</span> <span class="number">192.168.0.101</span> weight=<span class="number">1</span>;</div><div class="line"> <span class="attribute">server</span> <span class="number">192.168.0.102</span> weight=<span class="number">1</span>;</div><div class="line"> <span class="attribute">server</span> <span class="number">192.168.0.103</span> weight=<span class="number">1</span>;</div><div class="line"> }</div><div class="line"> <span class="attribute">location</span> <span class="regexp">~ .*.(jsp|do|action)</span> {</div><div class="line"> <span class="attribute">proxy_pass</span> <a href="http://tomcats" target="_blank" rel="external">http://tomcats</a>;</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</div>
</article>
<article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
<div class="post-block">
<link itemprop="mainEntityOfPage" href="http://eregg.com/2016/11/22/制作本地yum/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="name" content="eregg">
<meta itemprop="description" content="">
<meta itemprop="image" content="/uploads/avatar.jpg">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="学不可以已">
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2016/11/22/制作本地yum/" itemprop="url">制作本地yum</a></h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建于" itemprop="dateCreated datePublished" datetime="2016-11-22T09:38:47+08:00">
2016-11-22
</time>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h3 id="什么是YUM"><a href="#什么是YUM" class="headerlink" title="什么是YUM"></a><a href="#什么是YUM" title="什么是YUM"></a>什么是YUM</h3><p>YUM(全称为 Yellow dog Updater, Modified)是一个在Fedora和RedHat以及CentOS中的Shell前端软件包管理器。基于RPM包管理,能够从指定的服务器自动下载RPM包并且安装,可以自动处理依赖性关系,并且一次安装所有依赖的软件包,无须繁琐地一次次下载、安装。</p>
<h3 id="YUM的作用"><a href="#YUM的作用" class="headerlink" title="YUM的作用"></a><a href="#YUM的作用" title="YUM的作用"></a>YUM的作用</h3><ul>
<li><p>Typ在Linux上使用源码的方式安装软件非常满分,使用yum可以简化安装的过程</p>
<h3 id="YUM的常用命令"><a href="#YUM的常用命令" class="headerlink" title="YUM的常用命令"></a><a href="#YUM的常用命令" title="YUM的常用命令"></a>YUM的常用命令</h3><p>安装httpd并确认安装<figure class="highlight sh"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ yum instll -y httpd</div></pre></td></tr></table></figure></p>
</li>
</ul>
<p>列出所有可用的package和package组</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ yum list</div></pre></td></tr></table></figure>
<p>清除所有缓冲数据</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">yum clean all</div></pre></td></tr></table></figure>
<p>列出一个包所有依赖的包</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ yum deplist httpd</div></pre></td></tr></table></figure>
<p>删除httpd</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ yum remove httpd</div></pre></td></tr></table></figure>
<h3 id="为什么要制作本地YUM源"><a href="#为什么要制作本地YUM源" class="headerlink" title="为什么要制作本地YUM源"></a><a href="#为什么要制作本地YUM源" title="为什么要制作本地YUM源"></a>为什么要制作本地YUM源</h3><p>YUM源虽然可以简化我们在Linux上安装软件的过程,但是生产环境通常无法上网,不能连接外网的YUM源,所以接就无法使用yum命令安装软件了。为了在内网中也可以使用yum安装相关的软件,就需要配置yum源。</p>
<h3 id="YUM源的原理"><a href="#YUM源的原理" class="headerlink" title="YUM源的原理"></a><a href="#YUM源的原理" title="YUM源的原理"></a>YUM源的原理</h3><p>YUM源其实就是一个保存了多个RPM包的服务器,可以通过http的方式来检索、下载并安装相关的RPM包<br><img src="http://123.57.181.198/images/linux/localyum1.jpg" alt="yum原理图"></p>
<h3 id="制作本地YUM源"><a href="#制作本地YUM源" class="headerlink" title="制作本地YUM源"></a><a href="#制作本地YUM源" title="制作本地YUM源"></a>制作本地YUM源</h3><ul>
<li>准备一台Linux服务器</li>
<li>准置好这台服务器的IP地址</li>
<li>上传CentOS-6.7-x86_64-bin-DVD1.iso(此镜像包含了丰富的rpm包)到服务器</li>
<li><p>将CentOS-6.7-x86_64-bin-DVD1.iso镜像挂载到某个目录</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">$ mkdir /var/iso</div><div class="line">$ mount -o loop CentOS-6.7-x86_64-bin-DVD1.iso /var/iso</div></pre></td></tr></table></figure>
</li>
<li><p>修改本机上的YUM源配置文件,将源指向自己备份原有的YUM源的配置文件</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">$ <span class="built_in">cd</span> /etc/yum.repos.d/</div><div class="line">$ rename .repo .repo.bak *</div><div class="line">$ vi CentOS-Local.repo</div></pre></td></tr></table></figure><br><figure class="highlight ini"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="section">[base]</span></div><div class="line"><span class="attr">name</span>=CentOS-Local</div><div class="line"><span class="attr">baseurl</span>=file:///var/iso</div><div class="line"><span class="attr">gpgcheck</span>=<span class="number">1</span></div><div class="line"><span class="attr">gpgkey</span>=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-<span class="number">6</span></div></pre></td></tr></table></figure>
</li>
</ul>
<p>添加上面内容保存退出</p>
<ul>
<li><p>清除YUM缓冲</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ yum clean all</div></pre></td></tr></table></figure>
</li>
<li><p>列出可用的YUM源</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ yum repolist</div></pre></td></tr></table></figure>
</li>
<li><p>安装相应的软件</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ yum install -y httpd</div></pre></td></tr></table></figure>
</li>
<li><p>开启httpd使用浏览器访问<a href="http://192.168.0.100:80o如果访问不通,检查防火墙是否开启了80端口或关闭防火墙)" target="_blank" rel="external">http://192.168.0.100:80o如果访问不通,检查防火墙是否开启了80端口或关闭防火墙)</a></p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ service httpd start</div></pre></td></tr></table></figure>
</li>
<li><p>将YUM源配置到httpd(Apache Server)中,其他的服务器即可通过网络访问这个内网中的YUM源了</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ cp -r /var/iso/ /var/www/html/CentOS-6.7</div></pre></td></tr></table></figure>
</li>
<li><p>取消先前挂载的镜像</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ umount /var/iso</div></pre></td></tr></table></figure>
</li>
<li><p>在浏览器中访问<a href="http://192.168.0.100/CentOS-6.7/" target="_blank" rel="external">http://192.168.0.100/CentOS-6.7/</a><br><img src="http://123.57.181.198/images/linux/localyum.jpg" alt="将yum源做成一个web服务"></p>
</li>
<li><p>让其他需要安装RPM包的服务器指向这个YUM源,准备一台新的服务器,备份或删除原有的YUM源配置文件</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">$ <span class="built_in">cd</span> /etc/yum.repos.d/</div><div class="line">$ rename .repo .repo.bak *</div><div class="line">$ vi CentOS-Local.repo</div></pre></td></tr></table></figure><br><figure class="highlight ini"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="section">[base]</span></div><div class="line"><span class="attr">name</span>=CentOS-Local</div><div class="line"><span class="attr">baseurl</span>=http://<span class="number">192.168</span>.<span class="number">0.100</span>/CentOS-<span class="number">6.7</span>/</div><div class="line"><span class="attr">gpgcheck</span>=<span class="number">1</span></div><div class="line"><span class="attr">gpgkey</span>=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-<span class="number">6</span></div></pre></td></tr></table></figure>
</li>
</ul>
<p>添加上面内容保存退出</p>
<ul>
<li><p>在这台新的服务器上执行YUM的命令</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">$ yum clean all</div><div class="line">$ yum repolist</div></pre></td></tr></table></figure>
</li>
<li><p>安装相应的软件</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ yum install -y gcc</div></pre></td></tr></table></figure></li>
</ul>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</div>
</article>
<article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
<div class="post-block">
<link itemprop="mainEntityOfPage" href="http://eregg.com/2016/11/22/儒学三纲八目/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="name" content="eregg">
<meta itemprop="description" content="">
<meta itemprop="image" content="/uploads/avatar.jpg">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="学不可以已">
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2016/11/22/儒学三纲八目/" itemprop="url">儒学三纲八目</a></h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建于" itemprop="dateCreated datePublished" datetime="2016-11-22T09:37:35+08:00">
2016-11-22
</time>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<p> 大学之道,在明明德,在亲民,在止于至善。</p>
<p> 知止而后有定,定而后能静,静而后能安,安而后能虑,虑而后能得。物有本末,事有终始。知所先后,则近道矣。</p>
<p> 古之欲明明德于天下者,先治其国;欲治其国者,先齐其家;欲齐其家者,先修其身;欲修其身者,先正其心;欲正其心者,先诚其意;欲诚其意者,先致其知。致知在格物。物格而后知至,知至而后意诚,意诚而后心正,心正而后身修,身修而后家齐,家齐而后国治,国治而后天下平。自天子以至于庶人,壹是皆以修身为本。</p>
<p> 其本乱,而末治者否矣。其所厚者薄,而其所薄者厚,未之有也。</p>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</div>
</article>
<article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
<div class="post-block">
<link itemprop="mainEntityOfPage" href="http://eregg.com/2016/11/22/中庸之道的精髓/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="name" content="eregg">
<meta itemprop="description" content="">
<meta itemprop="image" content="/uploads/avatar.jpg">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="学不可以已">
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2016/11/22/中庸之道的精髓/" itemprop="url">中庸之道的精髓</a></h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建于" itemprop="dateCreated datePublished" datetime="2016-11-22T09:37:12+08:00">
2016-11-22
</time>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<p>中庸之道的理论基础是天人合一。通常人们讲天人合一主要是从哲学上讲,大都从《孟子》的“尽其心者,知其性也;知其性,则知天矣”(《尽心》)讲起,而忽略中庸之道的天人合一,更忽视了天人合一的真实含义。天人合一的真实含义是合一于至诚、至善,达到“致中和,天地位焉,万物育焉”、“唯天下至诚,为能尽其性。能尽其性则能尽人之性;能尽人之性,则能尽物之性;能尽物之性,则可以赞天地之化育;可以赞天地之化育,则可以与天地参矣”的境界。“与天地参”是天人合一。这才是《中庸》天人合一的真实含义。因而《中庸》始于“天命之谓性,率性之谓道,修道之谓教”而终于“‘上天之载,无声无臭。’至矣”。这就是圣人所要达到的最高境界,这才是真正意义上的天人合一。天人合一的天是善良美好的天,天人合一的人是像善良美好的天那样善良美好的人,天人合一就是人们自觉修养所达到像美好善良的天一样造福于人类和自然理想境界。 </p>
<p>中庸之道的天人合一表现在以下几个方面。 </p>
<p>(1)天道与人道合一 </p>
<p>天道就是诚,人道就是追求诚。这就是原天以启人,尽人以合天。也就是要求人道与天道相吻合。《中庸》说:“诚者,天之道也。诚之者,人之道也。诚者,不勉而中,不思而得,从容中道,圣人也。诚之者,择善而固执之者也。” </p>
<p>郑玄说:“言诚者天性也,诚之者,学而诚之者也。”孔颖达说:“此经明至诚之道,天之性也。则人当学其诚之性,是上天之疲乏不为而诚,不思而得,若天之性,有生杀信著四时,是天之道。诚之者人之道也者,言人能勉力学此至诚,是人之道也。不学则不得,故云人之道。诚者不勉而中,不思而得,从容中道,圣人也者,此复说上文诚者天之道也。唯圣人能然,谓不勉励而自中当于善,不思虑而自得于善,闲暇而自中乎道,以圣人性合于天道自然,故云圣人也。诚之者,择善而固执之者也,此复说上文诚之者,人之道也。谓由学而致此至诚,谓贤人也。言选择善事而坚固执之,行之不已,遂致至诚也。” </p>
<p>按照郑玄和孔颖达的解释,中庸之道的天道与人道合一为两种类型:一是圣人的天人合一,二是贤人的天人合一。圣人的天人合一是本能的天人合一。贤人的天人合一是通过学习而达到的天人合一。应该说,还有凡人的天人合一。《中庸》说:“或生而知之,或学而知之,或困而知之,及其知之,一也。或安而行之,或利而行之,或勉强而行之,及其成功,一也。”可以说,生而知之、安而行之的是圣人,学而知之、利而行之的是贤人,困而知之、勉强而行之的是凡人。不论是圣人、贤人,还是凡人,都能达到至诚、至善的天人合一境界。惟困而不学者不能致天人合一之境界也。 </p>
<p>(2)天性与人性合一 </p>
<p>天道与人道合一的目的就是要将天性与人性合一。天性是至善、至诚、至仁、至真的,那人性也应该是至善、至诚、至仁、至真的。只有使人性达到了那至善、至诚、至仁、至真的天性,才能称得上真正意义上的天人合一,才能创制天下的大纲,建立天下的大本,才能通晓天地化育万物的道理,才能达到中庸之道。 </p>
<p>(3)理性与情感合一 </p>
<p>中庸之道的天人合一还表现在理性与情感的合一。人们的喜怒哀乐是人的自然属性,是情感的表现,为了追求与天道、天性合一的至诚、至善、至仁、至真的人性,因而需要对情感加以约束和限制,所以《中庸》说:“喜怒哀乐之未发谓之中,发而皆中节谓之和”,只有“致中和”才能天人合一(“天地位焉,万物育焉”)。 </p>
<p>(4)鬼神与圣人合一 </p>
<p>中庸之道的天人合一还包括了鬼神与圣人合一。《中庸》第二十九章:“故君子之道,本诸身,征诸庶民;考诸三王而不谬,建诸天地而不悖,质诸鬼神而无疑,知天也;百世以俟圣人而不惑,知人也。是故君子动而世为天下道,行而世为天下法,言而世为天下则。”质证于鬼神没有疑问,就算是懂得认识了天;等到百代以后圣人出来也不会有疑问,就算是认识了人。说明中庸之道的天人合一中的天包括鬼神,人则包括圣人。真正意义上的天人合一含有圣人合一。鬼神是天地和祖先的总称。所以古人的天的要领里也包含了死人(祖先)的成分,天字本身就是大人站在天下,头顶蓝天。 </p>
<p>(5)外内合一 </p>
<p>中庸之道的天人合一还包括外内合一。《中庸》第二十五章揭示了外内合一。其文云:“诚者,自成也;而道,自道也。诚者,物之终始,不诚无物。是故君子诚之为贵。诚者非自成而已也,所在成物也。成己,仁也;成物,知也。性之德也。合外内之道也。故时措之宜也。”合外内之道,即外内合一,外内合天诚。所以中庸之道的天人合一,又合一于诚。这种外内合一又可以视为品德意识与品德行为的合一,或者说成己与成物的合一,或者说是知与行的合一。 </p>
<p>因而清朝杨亶骅《中庸提要》云:“《中庸》全书,以‘道不远人’句为宗旨,言人必溯源天天者,《戴记.礼运篇》夫子之言曰:‘人者,其天地之德阴阳之交,鬼神之会,五行之秀气也。’又曰:‘人者,天地之心也,五行之端也,食味、别声、被色而生者也。’子思明道,必原天地而兼鬼神以立说者,大抵皆宗此义。天命之谓性,即天地之德。命字已该交会秀气在内。‘仁者人也’,即天地之心。喜怒哀乐,即五行之端,而慎独二字,尤示人节欲以践形而尽性之要旨也。全书中以‘仁者人也’,‘诚之者人之道也’两‘人’字为枢纽。曰‘人莫不饮食也’,曰‘以人治人’,曰‘不可以不知人’,曰‘待其人而后行’,曰‘百世以俟圣人而不惑知人也’,每段提掇‘人’字,皆以阐‘道不远人’之旨。书之首以‘天’起,尾以‘天’结,言天、言天道者,不一而足。言知人即言知天,言人之道即言天之道。皆阐天人合一之旨。而鬼神为德,又以阐天人合一之真机也。配天者圣,浩浩其天者圣,而别无所谓道,别无所谓圣也,待其人而后行,圣人亦圣乎人而已。人者何?君臣、父子、夫妇、昆弟、朋友也。所以为人者仁也。人所以能仁者诚也。性为人性,道为人,教者教以为人也。孟子曰:‘人之所以异于禽兽者几希,庶民去之,君子存之。’子思明道,所以存人也。因其不远人,而目之曰庸,谓之曰不可离,始于慎独,极天参赞,祗完得生人本来面目,毫无加损于间焉。子思以中庸名书,‘庸德之行庸言之慎’,庸字于道不远人章点睛,自系全书宗旨。” </p>
<p>3.具体内容 </p>
<p>中庸之道的具体内容主要包括五达道、三达德、九经等。 </p>
<p>(1)五达道 </p>
<p>五达道主要是运用中庸之道调节五种人际关系。这五种基本人际关系是君臣、父子、夫妻、兄弟以及朋友的交往,将君臣关系视为上下关系,这五种人际关系就是天下通行的人际关系。《中庸》第十二章详细论述了夫妇的人际关系,将夫妇关系提到了非常高的地位。。其文云:“君子之遇而隐。夫妇之愚,可以与知焉;及其至也,虽圣人亦有所不知焉。夫妇之不肖,可以能行焉;及其至也,虽圣人亦有年不能焉 君子之道,造端乎夫妇,及其至也,察乎天地。”第十三章论述了父子、君臣、兄弟、朋友之达道。综观斯两章,五达道备焉。 </p>
<p>五达道就是天下通行的五种人际关系。通过正确处理这五种人际关系,达到太平和合的理想境界。诚如《礼运》所言:“故圣人耐以天下为一家,以中国为一人者,非意之也,必知其情,辟于其义,明于其利,达于其患,然后能为之。何谓人情?喜、怒、哀、惧、爱、欲,七者弗学而能。何谓人义?父慈、子孝、兄良、弟弟、夫义、妇听、长惠、幼顺、君仁、臣忠,十者谓之人义。讲信修睦,谓之人利;争夺相杀,谓之人患。故圣人之所以治人七情,修十义,讲信修睦,尚辞让,去争夺,舍礼何以治之?” </p>
<p>(2)三达德 </p>
<p>调节这些人际关系靠什么?靠人们内心的品德和智慧,因而就有了三达德。三达德,就是智、仁、勇。智、仁、勇是天下通行的品德,是用来调节上下、父子、夫妻、兄弟和朋友之间的关系的。智、仁、勇靠什么来培植呢?靠诚实、善良的品德意识来培植加固。所以《中庸》第二十章阐明道:“天下之达道五,所以行之者三。曰:君臣也,父子也,夫妇也,昆弟也,朋友之交也。五者,天下之达道也。知、仁、勇三者,天下之达德也,所以行之者一也。或生而知之,或学而知之,或困而知之,及其知之,一也。或安而行之,或困而行之,或勉强而行之,及其成功,一也。子曰:‘好学近乎知,力行近乎仁,知耻近乎勇。知斯三者,则知所以修身;知所以修身,则知所以治人;知所以治人,则知所以治天下国家矣。’” </p>
<p>(3)九经 </p>
<p>九经就是中庸之道用来治理天下国家以达到太平和合的九项具体工作。这九项工作是:修养自身,尊重贤人,爱护亲族,敬重大臣,体恤众臣,爱护百姓,劝勉各种工匠,优待远方来的客人,安抚诸侯。修养自身,就能够达到美好的人格;尊重人,就不至于迷惑;爱护亲族,叔伯兄弟之间就不会有怨恨;敬重大臣,治理政事就不至于糊涂;体恤群臣,士就会尽力予以报答;爱护老百姓,老百姓就会受到勉励;劝勉各种工匠,财货就能充足;优待远方来的客人,四方就会归顺,;安抚诸侯,天下就会敬服。要做好这九项工作,就必须用至诚、至仁、至善的爱心去充分体现中庸的美好人格。做好这九项工作,事实上也就处理调节好了九种人际关系。调节这九种人际关系是使天下国家达到太平和合理想的重要保证。“九经”的提出,是对《尚书.尧典》的“克明俊德,以亲九族,九族既睦,平章百姓,百姓昭明,协和万邦”的太平和合理想与“大学之道,在明明德、在亲民、在止于至善”的太平和合理想的继承和发展。 </p>
<p>4.主要原则 </p>
<p>中庸之道的主要原则有三条:一是慎独自修,二是忠恕宽容,三是至诚尽性。并分别论述于下。 </p>
<p>(1)慎独自修 </p>
<p>这一原则要求人们在自我修养的过程中,坚持自我教育、自我监督、自我约束。《中庸》第一章就提出了这一原则。其文云:“道也者,不可须臾离也,可离非道也。是故君子戒慎乎其所不睹,恐惧乎其所不闻。莫见乎隐,莫显乎微。故君子慎其独也。”人们必须严格地自觉地进行自我修养,尤其在一个人独处的时候,更应该谨慎地进行自我反省、自我约束、自我教育、自我监督。在别人听不到自己讲话的地方也十分谨慎,不说违背道德的话;在别人看不见自己物为的地方,也时刻属守中庸之道,做到至诚、至仁、至善、至圣,就必须坚持慎独自修的原则。坚持这一原则,其乐无穷,其用无穷,其功无穷。故《中庸》第三十三章云:“君子之道,淡而不厌,简而文,温而理。知远之近,知风之自,知微之显,可与入德矣。《诗》云:‘潜虽伏矣,亦孔之昭。’故君子内省不疚,无恶于志。君子之年不可及者,其唯人之所不见乎!《诗》云:‘相在尔室,尚不愧于屋漏。’故君子不动而敬,不言而信。《诗》曰:‘奏假无言,时靡有争。’故君子不赏而民劝,不怒而威于鈇钺 。《诗》曰:‘不显惟德,百辟其刑之。’是故君子笃恭而天下平。《诗》云:‘予怀明德,不大声以色。’子曰:‘声色之于以化民,末也。’《诗》曰:‘德輶如毛。’毛犹有伦,‘上天之载,无声无自。’至矣!” </p>
<p>(2)忠恕宽容 </p>
<p>这一原则要求人们将心比心、互相谅解、互相关心、互不损害、忠恕宽容、体仁而行、并行而不相悖。这一原则分别见一《中庸》十三章、三十章。 </p>
<p>“子曰:‘道不远人。人之为道而远人,不可以为道。’《诗》云:伐柯柯伐柯,其则不远。执柯以伐柯,睨而视之,犹以为远。故君子以人治人,改而止。忠恕违道不远。施诸己而不愿,亦勿施于人。” </p>
<p>这一思想源于孔子,曾子将其概括以传于世。《论语.里仁》记载孔子告戒曾子的话:“吾道一以贯之。”别的学生问曾参,这是什么意思。曾参说:“夫子之道,忠恕而已矣。”忠恕是为仁之方。说孔子的思想核心是忠恕之道,也就是说孔子的思想核心是为仁、行仁。孔子说恕便是“己所不欲,勿施于人”。“夫仁者,己欲立而立人,己欲达而达人。能近取譬,可谓仁之方也已。”所谓“能近取譬”就是将心比心,就是忠恕之道的具体实施。 </p>
<p>忠恕之道在《大学》里被称作“ 矩之道”。《大学》说:“所恶于上, 毋(勿)以使下。所恶于下,毋以先后。所恶于后,毋以从前。所恶于右,毋以交于左。所恶于左,毋以交于右。此这谓 矩之道。“这就是”己所不欲,勿施于人”的忠恕之道。不论是忠恕之道还是挈矩之道,其实质都是仁慈博爱,都是要求人们做到“我不欲人之加诸我也,吾亦欲无加诸人”(《论语.公冶长》)。 </p>
<p>《中庸》继承并发扬了孔子的忠恕之道和《大学》的挈矩之道。进一步提出了“以人治人”,要求人们用爱自己的心去爱他人,用责备他人的心来责备自己,用自己的真诚忠恕去感召人、感化人、塑造人。只要坚持忠恕之道,人们就会相安无事、和平共处,人们就会达到素其位而行、无入而不自得焉、上不怨天、下不尤人的思想境界。所以《中庸》说:“君子素其位而行,不愿乎其外。素富贵,行乎富贵。素贫贱,行乎贫贱。素夷锹,行乎夷锹。素患难,行乎患难。君子无入而不自得焉。在上位不陵下,在下位不援上,正己而不求于人,则无怨。上不怨天,下不尤人。故君子居易以俟命,小人行险以徼幸。子曰:‘射有似乎君子,失诸正鹄,反求诸其身。’” </p>
<p>(3)至诚尽性 </p>
<p>至诚尽性的原则 是施行中庸之道的重要原则。“唯天下至诚,为能尽其性。能尽其性,则能尽人之性;能尽人之性,则能尽物之性;能尽物之性,则可以赞天地之化育;可以赞天地之化育,则可以与天地参矣。”只有坚持至诚原则,才能充分发挥自己善良的天性。能够充分发挥自己善良的天性,就能感化他人、发挥他人的善良天性;能够发挥一切人的善良天性,就能充分发挥万物良天性;能够充分发挥万物的善良天性,就可以参与天地化育万物。便达到了至仁至善的境界;达到了至仁至善的境界,就可以同天地并列为三了。这就坚持至诚尽性原则所达到的理想境界,达到了这一理想境界也就找到了自己在宇宙间的真正位置。 </p>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</div>
</article>
<article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
<div class="post-block">
<link itemprop="mainEntityOfPage" href="http://eregg.com/2016/11/21/数据结构的基本概念/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="name" content="eregg">
<meta itemprop="description" content="">
<meta itemprop="image" content="/uploads/avatar.jpg">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="学不可以已">
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a class="post-title-link" href="/2016/11/21/数据结构的基本概念/" itemprop="url">数据结构的基本概念</a></h1>
<div class="post-meta">
<span class="post-time">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建于" itemprop="dateCreated datePublished" datetime="2016-11-21T04:39:36+08:00">
2016-11-21
</time>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h3 id="什么是数据结构"><a href="#什么是数据结构" class="headerlink" title="什么是数据结构"></a><a href="#什么是数据结构" title="什么是数据结构"></a>什么是数据结构</h3><p>数据结构是用来描述元素与元素之间关系的</p>
<h3 id="数据结构的逻辑关系"><a href="#数据结构的逻辑关系" class="headerlink" title="数据结构的逻辑关系"></a><a href="#数据结构的逻辑关系" title="数据结构的逻辑关系"></a>数据结构的逻辑关系</h3><p>简而言之,逻辑结构就是数据元素间的逻辑关系,他与数据存储无关,是独立于计算机的。</p>
<p>逻辑结构可细分为4类</p>
<ul>
<li>集合:数据元素间,“同属一个集合”,而无其他关系(没有前驱后继关系)</li>
<li>线性结构:一对一的关系,如线性表,栈,队列(唯一的前驱或后继关系)</li>
<li>树形结构:一对多的关系,如树(一个前驱,多个后继)</li>
<li>图状结构:多对多的关系,如图(多个前驱,多个后继)</li>
</ul>
<h3 id="数据结构的物理关系"><a href="#数据结构的物理关系" class="headerlink" title="数据结构的物理关系"></a><a href="#数据结构的物理关系" title="数据结构的物理关系"></a>数据结构的物理关系</h3><p>数据结构在计算机中的表示(又称映像),称为数据的物理结构,或称存储结构,它所研究的是数据结构在计算机中实现的方法。</p>
<p>存储结构可分为四大类:顺序存储,链式存储,索引,散列。</p>
<ul>
<li>顺序存储结构:借助元素在内存中的相对位置来表示数据元素之间的逻辑关系</li>
<li>链式存储结构:借助元素存储的地址指针来表示数据元素之间的逻辑关系(节点中有一个指针指向下一个节点的地址……)</li>
</ul>
<h3 id="数据的逻辑结构与物理结构的关系"><a href="#数据的逻辑结构与物理结构的关系" class="headerlink" title="数据的逻辑结构与物理结构的关系"></a><a href="#数据的逻辑结构与物理结构的关系" title="数据的逻辑结构与物理结构的关系"></a>数据的逻辑结构与物理结构的关系</h3><ul>
<li>算法设计:逻辑结构</li>
<li>算法实现:物理结构</li>
</ul>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</div>
</article>
</section>
</div>
</div>
<div class="sidebar-toggle">
<div class="sidebar-toggle-line-wrap">
<span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
<span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
<span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
</div>
</div>
<aside id="sidebar" class="sidebar">
<div class="sidebar-inner">
<section class="site-overview sidebar-panel sidebar-panel-active">
<div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
<img class="site-author-image" itemprop="image"
src="/uploads/avatar.jpg"
alt="eregg" />
<p class="site-author-name" itemprop="name">eregg</p>
<p class="site-description motion-element" itemprop="description">青,取之于蓝,而青于蓝</p>
</div>
<nav class="site-state motion-element">
<div class="site-state-item site-state-posts">
<a href="/archives/">
<span class="site-state-item-count">10</span>
<span class="site-state-item-name">日志</span>
</a>
</div>
<div class="site-state-item site-state-tags">
<a href="/tags/index.html">
<span class="site-state-item-count">31</span>
<span class="site-state-item-name">标签</span>
</a>
</div>
</nav>
<div class="feed-link motion-element">
<a href="/atom.xml" rel="alternate">
<i class="fa fa-rss"></i>
RSS
</a>
</div>
<div class="links-of-author motion-element">
<span class="links-of-author-item">
<a href="https://github.com/eregg" target="_blank" title="GitHub">
<i class="fa fa-fw fa-github"></i>GitHub</a>
</span>
<span class="links-of-author-item">
<a href="mailto:ereggmail@163.com" target="_blank" title="E-Mail">
<i class="fa fa-fw fa-envelope"></i>E-Mail</a>
</span>
</div>
</section>
</div>
</aside>
</div>
</main>
<footer id="footer" class="footer">
<div class="footer-inner">
<div class="copyright" >
© 2015 —
<span itemprop="copyrightYear">2017</span>
<span class="with-love">
<i class="fa fa-heart"></i>
</span>
<span class="author" itemprop="copyrightHolder">eregg</span>
</div>
<div class="powered-by">由 <a class="theme-link" href="https://hexo.io">Hexo</a> 强力驱动</div>
<span class="post-meta-divider">|</span>
<div class="theme-info">主题 — <a class="theme-link" href="https://github.com/iissnan/hexo-theme-next">NexT.Mist</a> v5.1.2</div>
</div>
</footer>
<div class="back-to-top">
<i class="fa fa-arrow-up"></i>
</div>
</div>
<script type="text/javascript">
if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
window.Promise = null;
}
</script>
<script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>
<script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>
<script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>
<script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>
<script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
<script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>
<script type="text/javascript" src="/lib/canvas-nest/canvas-nest.min.js"></script>
<script type="text/javascript" src="/js/src/utils.js?v=5.1.2"></script>
<script type="text/javascript" src="/js/src/motion.js?v=5.1.2"></script>
<script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.2"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.1.2"></script>
<script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.2"></script>
</body>
</html>
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。