Rust入门之并发编程基础(三)

Rust入门之并发编程基础(三)

题记:6月底7月初,结束北京的工作生活回到二线省会城市发展了,鸽了较久了,要继续坚持学习Rust,坚持写博客。

背景

我们平时使用计算机完成某项工作的时候,往往可以同时执行多个任务,比如可以编程的时候同时播放音乐,就算是单核CPU也是如此。这是因为现代计算机操作系统会使用**“中断机制”**来执行任务,任务可以分为:

  • “CPU 密集型“或者“计算密集型”
  • ”IO 密集型“

根据这两种类型,又可以有针对性的利用操作系统的”中断机制“提供计算机同时执行多任务的效率。大多数函数调用都是会发生阻塞的,等待当前执行完成才会继续执行后续的动作,如果在一个程序中有多个任务,多个任务中某些任务阻塞时可以不影响其他任务执行,也就是异步执行多个任务,这样效率就会提高很多了。多线程异步执行程序就显得尤为重要了。

讨论一下并发和并行

比如给员工分配任务,如果分配给一个员工多个任务,这个员工在任务一个任务完成前同时处理多个任务,这就类似计算机操作系统的中断机制,这就是并发

当将多个任务在多个员工中分配执行,每个员工分配一个任务并单独处理它,这就是并行。每个组员可以真正的同时进行工作。

如果一个任务执行必须依赖另一个任务,那么任务之间必须串行的执行,一个处理了再处理下一个任务。并行和并发也会发生相互交叉(阻塞)如果某个程序中的某几个任务的并发执行都需要等待另一个任务的完成,可能就会集中时间做这个任务,那么就都无法并行工作了。

并发 VS 并行

特征 并发 并行 串行
执行方式 任务交替执行 任务同时执行 顺序执行
类比模型 单员工轮流处理多个任务 多员工各处理单个任务 单任务完成后才能开始下一个
资源需求 单核或多核 多核必需 单核或多核
执行时机 任务可能重叠 任务真正同时 任务顺序执行

同样的基础动作也作用于软件和硬件。在单核CPU的计算机上,CPU一次只能执行一个操作,不过它仍然是并发工作,借助像线程,进程和异步(async)等工具,计算机可以暂停一个活动,并在最终切换回第一个活动执行之前切换到其它活动。在一个多核CPU的计算机上,它也可以并行工作,一个核心执行一个任务,同时另一个核心可以执行其他不相关的工作,而且这些工作实际上是同时发生的。

Rust 异步编程主要处理并发性,取决于硬件、操作系统和所使用的异步运行时(async runtime),并发也有可能在底层使用了并行。下面将详细的讨论Rust 异步编程是如何工作的。

Rust 异步编程的核心组件:future、async、await

Rust 异步编程的三个重要关键元素:

  1. futures
  2. async 关键字
  3. await 关键字

future 是一个现在还没准备好,未来会返回结果的一个值。类似Java 语言中也有类似的Future概念。Rust提供了 Future trait 作为基础组件。

async 关键字可以用于代码块或函数,表明它们可以被中断或恢复。在一个async 块或者 async 函数中,可以使用 await 关键字来等待一个 future 准备就绪,这个过程称之为等待一个 future。每一个等待future 的地方都可能是一个async 块或async函数中断并随后恢复的点。检查一个future 并查看其值是否准备就绪的过程被称之为轮询(polling)。

future 的特点:

  • Rust编译器将 async/await 代码转换为使用 Future trait 的等效代码
    • 类似 for 循环被转换为使用 Iterator trait
  • 开发者可以为自定义数据类型实现 Future trait
    • 提供统一的接口但允许实现不同的异步操作实现

Rust 官方为了大家学习实验异步操作,创建了一个 trpl crate(trpl 是 “The Rust Programming Language” 的缩写)。它重导出了你需要的所有类型、traits 和函数,它们主要来自于 futurestokio crates。

  • futures crate 是一个 Rust 异步代码实验的官方仓库,也正是 Future 最初设计的地方。
  • Tokio 是目前 Rust 中应用最广泛的异步运行时(async runtime),特别是(但不仅是!)web 应用。这里还有其他优秀的运行时,它们可能更适合你的需求。我们在 trpl 的底层使用 Tokio 是因为它经过了充分测试且广泛使用。

接下来上代码,利用 trpl 提供的多种组件来编写第一个异步程序。我们构建了一个小的命令行工具来抓取两个网页,拉取各自的 </code> 元素,并打印出第一个完成全部过程的标题。先创建一个rust项目,添加 <code>trpl</code> 库。</p> <p><strong>Cargo.toml:</strong></p> <pre><code class="prism language-toml">[package] name = "hello-async" version = "0.1.0" edition = "2021" [dependencies] trpl = "0.2.0" </code></pre> <p><strong>main.rs:</strong></p> <pre><code class="prism language-rust"><span class="token keyword">use</span> <span class="token namespace">trpl<span class="token punctuation">::</span></span><span class="token class-name">Html</span><span class="token punctuation">;</span> <span class="token keyword">use</span> <span class="token namespace">trpl<span class="token punctuation">::</span></span><span class="token class-name">Either</span><span class="token punctuation">;</span> <span class="token keyword">async</span> <span class="token keyword">fn</span> <span class="token function-definition function">page_title</span><span class="token punctuation">(</span>url<span class="token punctuation">:</span> <span class="token operator">&</span><span class="token keyword">str</span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token punctuation">(</span><span class="token operator">&</span><span class="token keyword">str</span><span class="token punctuation">,</span> <span class="token class-name">Option</span><span class="token operator"><</span><span class="token class-name">String</span><span class="token operator">></span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 传入的任意 URL,使用 await 等待响应,因为Rust的futures是惰性的,只有调用await时,才会执行异步操作</span> <span class="token keyword">let</span> response <span class="token operator">=</span> <span class="token namespace">trpl<span class="token punctuation">::</span></span><span class="token function">get</span><span class="token punctuation">(</span>url<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token keyword">await</span><span class="token punctuation">;</span> <span class="token keyword">let</span> response_text <span class="token operator">=</span> response<span class="token punctuation">.</span><span class="token function">text</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token keyword">await</span><span class="token punctuation">;</span> <span class="token keyword">let</span> title <span class="token operator">=</span> <span class="token class-name">Html</span><span class="token punctuation">::</span><span class="token function">parse</span><span class="token punctuation">(</span><span class="token operator">&</span>response_text<span class="token punctuation">)</span> <span class="token punctuation">.</span><span class="token function">select_first</span><span class="token punctuation">(</span><span class="token string">"title"</span><span class="token punctuation">)</span> <span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token closure-params"><span class="token closure-punctuation punctuation">|</span>title_element<span class="token closure-punctuation punctuation">|</span></span> title_element<span class="token punctuation">.</span><span class="token function">inner_html</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">(</span>url<span class="token punctuation">,</span> title<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">fn</span> <span class="token function-definition function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 接收参数,两个参数分别是两个URL</span> <span class="token keyword">let</span> args<span class="token punctuation">:</span> <span class="token class-name">Vec</span><span class="token operator"><</span><span class="token class-name">String</span><span class="token operator">></span> <span class="token operator">=</span> <span class="token namespace">std<span class="token punctuation">::</span>env<span class="token punctuation">::</span></span><span class="token function">args</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">collect</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token namespace">trpl<span class="token punctuation">::</span></span><span class="token function">run</span><span class="token punctuation">(</span><span class="token keyword">async</span> <span class="token punctuation">{</span> <span class="token keyword">let</span> title_fut_1 <span class="token operator">=</span> <span class="token function">page_title</span><span class="token punctuation">(</span><span class="token operator">&</span>args<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">let</span> title_fut_2 <span class="token operator">=</span> <span class="token function">page_title</span><span class="token punctuation">(</span><span class="token operator">&</span>args<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">let</span> <span class="token punctuation">(</span>url<span class="token punctuation">,</span> maybe_title<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token keyword">match</span> <span class="token namespace">trpl<span class="token punctuation">::</span></span><span class="token function">race</span><span class="token punctuation">(</span>title_fut_1<span class="token punctuation">,</span> title_fut_2<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token keyword">await</span> <span class="token punctuation">{</span> <span class="token class-name">Either</span><span class="token punctuation">::</span><span class="token class-name">Left</span><span class="token punctuation">(</span>left<span class="token punctuation">)</span> <span class="token operator">=></span> left<span class="token punctuation">,</span> <span class="token class-name">Either</span><span class="token punctuation">::</span><span class="token class-name">Right</span><span class="token punctuation">(</span>right<span class="token punctuation">)</span> <span class="token operator">=></span> right<span class="token punctuation">,</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token macro property">println!</span><span class="token punctuation">(</span><span class="token string">"{url} returned first"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">match</span> maybe_title <span class="token punctuation">{</span> <span class="token class-name">Some</span><span class="token punctuation">(</span>title<span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token macro property">println!</span><span class="token punctuation">(</span><span class="token string">"Its page title is: '{title}'"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token class-name">None</span> <span class="token operator">=></span> <span class="token macro property">println!</span><span class="token punctuation">(</span><span class="token string">"Its title could not be parsed."</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> </code></pre> <p><code>async</code> 修饰 page_title 函数,说明这个函数是一个异步函数。<code>trpl::get(url)</code> 去调用url地址返回响应,这里需要等待时间,这个函数也是用 <code>async</code> 修饰了表示它也是一个异步函数并返回future,这里加上<code>await</code>,表示我们要等待这个future 返回响应。同样<code>response.text()</code> 也是异步的,这里也使用 <code>await</code> 等待返回结果。 响应文本拿到后再使用<code>Html::parse</code> 解析。</p> <p>这里要注意因为<strong>Rust的futures是惰性的,只有调用await时,才会执行异步操作</strong>,然后这里也可以改为链式调用,让代码更加简洁。</p> <p><code>page_title</code> 这个函数使用了<code>async</code>修饰,当函数使用<code>async</code>的时候,就会将函数转换为返回<code>Future</code>的普通函数。</p> <p>这个示例分别由用户提供的 URL 调用 <code>page_title</code> 开始。我们将调用 <code>page_title</code> 产生的 future 分别保存为 <code>title_fut_1</code> 和 <code>title_fut_2</code>。请记住,它们还没有进行任何工作,因为 future 是惰性的,并且我们还没有 <code>await</code> 它们。接着我们将 futures 传递给 <code>trpl::race</code>,它返回一个值表明哪个传递的 future 最先返回。</p> <h3>并发与async</h3> <p>使用异步编程解决一些并发问题,这里更多关注线程与future的区别。</p> <p><strong>代码示例:</strong></p> <pre><code class="prism language-rust"><span class="token keyword">use</span> <span class="token namespace">std<span class="token punctuation">::</span>time<span class="token punctuation">::</span></span><span class="token class-name">Duration</span><span class="token punctuation">;</span> <span class="token keyword">fn</span> <span class="token function-definition function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token namespace">trpl<span class="token punctuation">::</span></span><span class="token function">run</span><span class="token punctuation">(</span><span class="token keyword">async</span> <span class="token punctuation">{</span> <span class="token namespace">trpl<span class="token punctuation">::</span></span><span class="token function">spawn_task</span><span class="token punctuation">(</span> <span class="token keyword">async</span> <span class="token punctuation">{</span> <span class="token keyword">for</span> i <span class="token keyword">in</span> <span class="token number">1</span><span class="token punctuation">..</span><span class="token number">10</span> <span class="token punctuation">{</span> <span class="token macro property">println!</span><span class="token punctuation">(</span><span class="token string">"hi numnber {i} from the first task!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token namespace">trpl<span class="token punctuation">::</span></span><span class="token function">sleep</span><span class="token punctuation">(</span><span class="token class-name">Duration</span><span class="token punctuation">::</span><span class="token function">from_millis</span><span class="token punctuation">(</span><span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token keyword">await</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">for</span> i <span class="token keyword">in</span> <span class="token number">1</span><span class="token punctuation">..</span><span class="token number">5</span> <span class="token punctuation">{</span> <span class="token macro property">println!</span><span class="token punctuation">(</span><span class="token string">"hi number {i} from the second task!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token namespace">trpl<span class="token punctuation">::</span></span><span class="token function">sleep</span><span class="token punctuation">(</span><span class="token class-name">Duration</span><span class="token punctuation">::</span><span class="token function">from_millis</span><span class="token punctuation">(</span><span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token keyword">await</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> </code></pre> <p><strong>执行结果:</strong></p> <pre><code class="prism language-bash">hi number <span class="token number">1</span> from the second task<span class="token operator">!</span> hi numnber <span class="token number">1</span> from the first task<span class="token operator">!</span> hi number <span class="token number">2</span> from the second task<span class="token operator">!</span> hi numnber <span class="token number">2</span> from the first task<span class="token operator">!</span> hi number <span class="token number">3</span> from the second task<span class="token operator">!</span> hi numnber <span class="token number">3</span> from the first task<span class="token operator">!</span> hi number <span class="token number">4</span> from the second task<span class="token operator">!</span> hi numnber <span class="token number">4</span> from the first task<span class="token operator">!</span> hi numnber <span class="token number">5</span> from the first task<span class="token operator">!</span> </code></pre> <p>根据执行结果可以看出。first task 在 second task 执行结束后也停止了,这是因为主任务(second task)已经停止,在主任务中创建的异步任务(first task)也会停止。如果要运行first task 直到结束,就需要一个<code>join</code>(join handle)来等待第一个任务完成。对于线程来说,可以使用<code>join</code> 方法来阻塞直到线程结束运行。在这里可以使用<code>await</code> 达到相同的效果。</p> <p><strong>添加handle.await.unwrap():</strong></p> <pre><code class="prism language-rust"><span class="token keyword">use</span> <span class="token namespace">std<span class="token punctuation">::</span>time<span class="token punctuation">::</span></span><span class="token class-name">Duration</span><span class="token punctuation">;</span> <span class="token keyword">fn</span> <span class="token function-definition function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token namespace">trpl<span class="token punctuation">::</span></span><span class="token function">run</span><span class="token punctuation">(</span><span class="token keyword">async</span> <span class="token punctuation">{</span> <span class="token keyword">let</span> handle <span class="token operator">=</span> <span class="token namespace">trpl<span class="token punctuation">::</span></span><span class="token function">spawn_task</span><span class="token punctuation">(</span> <span class="token keyword">async</span> <span class="token punctuation">{</span> <span class="token keyword">for</span> i <span class="token keyword">in</span> <span class="token number">1</span><span class="token punctuation">..</span><span class="token number">10</span> <span class="token punctuation">{</span> <span class="token macro property">println!</span><span class="token punctuation">(</span><span class="token string">"hi numnber {i} from the first task!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token namespace">trpl<span class="token punctuation">::</span></span><span class="token function">sleep</span><span class="token punctuation">(</span><span class="token class-name">Duration</span><span class="token punctuation">::</span><span class="token function">from_millis</span><span class="token punctuation">(</span><span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token keyword">await</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">for</span> i <span class="token keyword">in</span> <span class="token number">1</span><span class="token punctuation">..</span><span class="token number">5</span> <span class="token punctuation">{</span> <span class="token macro property">println!</span><span class="token punctuation">(</span><span class="token string">"hi number {i} from the second task!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token namespace">trpl<span class="token punctuation">::</span></span><span class="token function">sleep</span><span class="token punctuation">(</span><span class="token class-name">Duration</span><span class="token punctuation">::</span><span class="token function">from_millis</span><span class="token punctuation">(</span><span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token keyword">await</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> handle<span class="token punctuation">.</span><span class="token keyword">await</span><span class="token punctuation">.</span><span class="token function">unwrap</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> </code></pre> <p><strong>执行结果:</strong></p> <pre><code class="prism language-rust">hi number <span class="token number">1</span> from the second <span class="token macro property">task!</span> hi numnber <span class="token number">1</span> from the first <span class="token macro property">task!</span> hi number <span class="token number">2</span> from the second <span class="token macro property">task!</span> hi numnber <span class="token number">2</span> from the first <span class="token macro property">task!</span> hi numnber <span class="token number">3</span> from the first <span class="token macro property">task!</span> hi number <span class="token number">3</span> from the second <span class="token macro property">task!</span> hi number <span class="token number">4</span> from the second <span class="token macro property">task!</span> hi numnber <span class="token number">4</span> from the first <span class="token macro property">task!</span> hi numnber <span class="token number">5</span> from the first <span class="token macro property">task!</span> hi numnber <span class="token number">6</span> from the first <span class="token macro property">task!</span> hi numnber <span class="token number">7</span> from the first <span class="token macro property">task!</span> hi numnber <span class="token number">8</span> from the first <span class="token macro property">task!</span> hi numnber <span class="token number">9</span> from the first <span class="token macro property">task!</span> </code></pre> <h3>消息传递</h3> <p>再使用前面讲过的消息传递的例子,这次使用<code> future</code> 演示线程间消息传递,来看看基于 <code>future</code> 的并发和基于线程的并发的差异。</p> <p><code>trpl</code> 中的 <code>rx.recv() </code>返回一个<code>future</code>,是异步的。之前我们使用<code>let s = rx.recv();</code> 是同步阻塞的。</p> <pre><code class="prism language-rust"><span class="token keyword">let</span> s<span class="token punctuation">:</span> <span class="token class-name">Result</span><span class="token operator"><</span><span class="token class-name">String</span><span class="token punctuation">,</span> <span class="token namespace">mpsc<span class="token punctuation">::</span></span><span class="token class-name">RecvError</span><span class="token operator">></span> <span class="token operator">=</span> rx<span class="token punctuation">.</span><span class="token function">recv</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> </code></pre> <p><strong>代码示例:</strong></p> <pre><code class="prism language-rust"><span class="token keyword">fn</span> <span class="token function-definition function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token namespace">trpl<span class="token punctuation">::</span></span><span class="token function">run</span><span class="token punctuation">(</span><span class="token keyword">async</span> <span class="token punctuation">{</span> <span class="token keyword">let</span> <span class="token punctuation">(</span>tx<span class="token punctuation">,</span> <span class="token keyword">mut</span> rx<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token namespace">trpl<span class="token punctuation">::</span></span><span class="token function">channel</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">let</span> val <span class="token operator">=</span> <span class="token class-name">String</span> <span class="token punctuation">::</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token string">"hi"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> tx<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>val<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">unwrap</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// trpl channel rx.recv() 返回的是一个future, 是异步非阻塞版本</span> <span class="token keyword">let</span> received <span class="token operator">=</span> rx<span class="token punctuation">.</span><span class="token function">recv</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token keyword">await</span><span class="token punctuation">.</span><span class="token function">unwrap</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token macro property">println!</span><span class="token punctuation">(</span><span class="token string">"get: {received}"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> </code></pre> <p>上面的代码中,发送到接收都是顺序执行的也就是同步的,因为它们都在同一个<code>async</code> 代码块当中。接下来修改一下代码,我们发送多个消息,让<strong>多个消息异步发送和接收</strong>,而不是都发送完才可以接收。</p> <p>将发送端和接收端分别放到各自的<code>async</code> 块中,返回两个future,再使用trpl::join(),返回一个新的future.,再调用await等待两个future完成。</p> <p><strong>代码示例:</strong></p> <pre><code class="prism language-rust"><span class="token keyword">use</span> <span class="token namespace">std<span class="token punctuation">::</span>time<span class="token punctuation">::</span></span><span class="token class-name">Duration</span><span class="token punctuation">;</span> <span class="token keyword">fn</span> <span class="token function-definition function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token namespace">trpl<span class="token punctuation">::</span></span><span class="token function">run</span><span class="token punctuation">(</span><span class="token keyword">async</span> <span class="token punctuation">{</span> <span class="token keyword">let</span> <span class="token punctuation">(</span>tx<span class="token punctuation">,</span> <span class="token keyword">mut</span> rx<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token namespace">trpl<span class="token punctuation">::</span></span><span class="token function">channel</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 发送放到一个future 中</span> <span class="token keyword">let</span> tx_future <span class="token operator">=</span> <span class="token keyword">async</span> <span class="token keyword">move</span> <span class="token punctuation">{</span> <span class="token keyword">let</span> vals <span class="token operator">=</span> <span class="token macro property">vec!</span><span class="token punctuation">[</span> <span class="token class-name">String</span><span class="token punctuation">::</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token string">"Hi"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token class-name">String</span><span class="token punctuation">::</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token string">"from"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token class-name">String</span><span class="token punctuation">::</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token string">"the"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token class-name">String</span><span class="token punctuation">::</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token string">"future"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token keyword">for</span> val <span class="token keyword">in</span> vals <span class="token punctuation">{</span> tx<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>val<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">unwrap</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token namespace">trpl<span class="token punctuation">::</span></span><span class="token function">sleep</span><span class="token punctuation">(</span><span class="token class-name">Duration</span><span class="token punctuation">::</span><span class="token function">from_millis</span><span class="token punctuation">(</span><span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token keyword">await</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">let</span> rx_future <span class="token operator">=</span> <span class="token keyword">async</span> <span class="token punctuation">{</span> <span class="token keyword">while</span> <span class="token keyword">let</span> <span class="token class-name">Some</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span> <span class="token operator">=</span> rx<span class="token punctuation">.</span><span class="token function">recv</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token keyword">await</span> <span class="token punctuation">{</span> <span class="token macro property">println!</span><span class="token punctuation">(</span><span class="token string">"received: {value}"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token comment">// 使用 join 接收两个future,返回一个新的future</span> <span class="token namespace">trpl<span class="token punctuation">::</span></span><span class="token function">join</span><span class="token punctuation">(</span>tx_future<span class="token punctuation">,</span> rx_future<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token keyword">await</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> </code></pre> <p><strong>执行结果:</strong></p> <p>每隔500 ms 接收一个消息并打印。</p> <pre><code class="prism language-bash">received: Hi received: from received: the received: future </code></pre> <p><code>let tx_future = async move {</code> 这里使用了move 关键字,将 <code>tx</code> 移动(move)进异步代码块,它会在代码块结束后立刻被丢弃,这样<code>tx</code>销毁了,<code>rx</code> 也就在接收后优雅的关闭。</p> <p><strong>多生产者代码示例:</strong></p> <pre><code class="prism language-rust"><span class="token keyword">use</span> <span class="token namespace">std<span class="token punctuation">::</span>time<span class="token punctuation">::</span></span><span class="token class-name">Duration</span><span class="token punctuation">;</span> <span class="token keyword">fn</span> <span class="token function-definition function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token namespace">trpl<span class="token punctuation">::</span></span><span class="token function">run</span><span class="token punctuation">(</span><span class="token keyword">async</span> <span class="token punctuation">{</span> <span class="token keyword">let</span> <span class="token punctuation">(</span>tx<span class="token punctuation">,</span> <span class="token keyword">mut</span> rx<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token namespace">trpl<span class="token punctuation">::</span></span><span class="token function">channel</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">let</span> tx1 <span class="token operator">=</span> tx<span class="token punctuation">.</span><span class="token function">clone</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 发送放到一个future 中</span> <span class="token keyword">let</span> tx1_future <span class="token operator">=</span> <span class="token keyword">async</span> <span class="token keyword">move</span> <span class="token punctuation">{</span> <span class="token keyword">let</span> vals <span class="token operator">=</span> <span class="token macro property">vec!</span><span class="token punctuation">[</span> <span class="token class-name">String</span><span class="token punctuation">::</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token string">"Hi"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token class-name">String</span><span class="token punctuation">::</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token string">"from"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token class-name">String</span><span class="token punctuation">::</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token string">"the"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token class-name">String</span><span class="token punctuation">::</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token string">"future"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token keyword">for</span> val <span class="token keyword">in</span> vals <span class="token punctuation">{</span> tx1<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>val<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">unwrap</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token namespace">trpl<span class="token punctuation">::</span></span><span class="token function">sleep</span><span class="token punctuation">(</span><span class="token class-name">Duration</span><span class="token punctuation">::</span><span class="token function">from_millis</span><span class="token punctuation">(</span><span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token keyword">await</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">let</span> rx_future <span class="token operator">=</span> <span class="token keyword">async</span> <span class="token punctuation">{</span> <span class="token keyword">while</span> <span class="token keyword">let</span> <span class="token class-name">Some</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span> <span class="token operator">=</span> rx<span class="token punctuation">.</span><span class="token function">recv</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token keyword">await</span> <span class="token punctuation">{</span> <span class="token macro property">println!</span><span class="token punctuation">(</span><span class="token string">"received: {value}"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">let</span> tx_future <span class="token operator">=</span> <span class="token keyword">async</span> <span class="token keyword">move</span> <span class="token punctuation">{</span> <span class="token keyword">let</span> vals <span class="token operator">=</span> <span class="token macro property">vec!</span><span class="token punctuation">[</span> <span class="token class-name">String</span><span class="token punctuation">::</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token string">"Hi"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token class-name">String</span><span class="token punctuation">::</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token string">"from"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token class-name">String</span><span class="token punctuation">::</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token string">"the"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token class-name">String</span><span class="token punctuation">::</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token string">"future"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token keyword">for</span> val <span class="token keyword">in</span> vals <span class="token punctuation">{</span> tx<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>val<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">unwrap</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token namespace">trpl<span class="token punctuation">::</span></span><span class="token function">sleep</span><span class="token punctuation">(</span><span class="token class-name">Duration</span><span class="token punctuation">::</span><span class="token function">from_millis</span><span class="token punctuation">(</span><span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token keyword">await</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token comment">// 使用 join 接收两个future,返回一个新的future</span> <span class="token namespace">trpl<span class="token punctuation">::</span></span><span class="token function">join3</span><span class="token punctuation">(</span>tx1_future<span class="token punctuation">,</span> tx_future<span class="token punctuation">,</span> rx_future<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token keyword">await</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> </code></pre> <h3>后续</h3> <p>本文讨论了并发和人并行的区别,也讲了 future,await 再异步编程中的作用,future 代表未来会返回结果值的一个变量,await表示要等待future返回结果。</p> <p>本文记录根据Rust程序设计语言(Rust 中文社区翻译)学习笔记,但是发现这个网页版电子书,异步这里讲的很抽象,后续经过更深入的学习会再更新异步编程的部分。</p> </div> </div> </div> </div> </div> <!--PC和WAP自适应版--> <div id="SOHUCS" sid="1946691016677453824"></div> <script type="text/javascript" src="/views/front/js/chanyan.js"></script> <!-- 文章页-底部 动态广告位 --> <div class="youdao-fixed-ad" id="detail_ad_bottom"></div> </div> <div class="col-md-3"> <div class="row" id="ad"> <!-- 文章页-右侧1 动态广告位 --> <div id="right-1" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad"> <div class="youdao-fixed-ad" id="detail_ad_1"> </div> </div> <!-- 文章页-右侧2 动态广告位 --> <div id="right-2" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad"> <div class="youdao-fixed-ad" id="detail_ad_2"></div> </div> <!-- 文章页-右侧3 动态广告位 --> <div id="right-3" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad"> <div class="youdao-fixed-ad" id="detail_ad_3"></div> </div> </div> </div> </div> </div> </div> <div class="container"> <h4 class="pt20 mb15 mt0 border-top">你可能感兴趣的:(Rust入门之并发编程基础(三))</h4> <div id="paradigm-article-related"> <div class="recommend-post mb30"> <ul class="widget-links"> <li><a href="/article/1950233451282100224.htm" title="python 读excel每行替换_Python脚本操作Excel实现批量替换功能" target="_blank">python 读excel每行替换_Python脚本操作Excel实现批量替换功能</a> <span class="text-muted">weixin_39646695</span> <a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/%E8%AF%BBexcel%E6%AF%8F%E8%A1%8C%E6%9B%BF%E6%8D%A2/1.htm">读excel每行替换</a> <div>Python脚本操作Excel实现批量替换功能大家好,给大家分享下如何使用Python脚本操作Excel实现批量替换。使用的工具Openpyxl,一个处理excel的python库,处理excel,其实针对的就是WorkBook,Sheet,Cell这三个最根本的元素~明确需求原始excel如下我们的目标是把下面excel工作表的sheet1表页A列的内容“替换我吧”批量替换为B列的“我用来替换的</div> </li> <li><a href="/article/1950233072825856000.htm" title="三菱PLC全套学习资料及应用手册" target="_blank">三菱PLC全套学习资料及应用手册</a> <span class="text-muted">good2know</span> <div>本文还有配套的精品资源,点击获取简介:三菱PLC作为工业自动化领域的核心设备,其系列产品的学习和应用需要全面深入的知识。本次资料包为学习者提供从基础到进阶的全方位学习资源,包括各种型号PLC的操作手册、编程指南、软件操作教程以及实际案例分析,旨在帮助用户系统掌握PLC的编程语言、指令系统及在各类工业应用中的实施。1.三菱PLC基础知识入门1.1PLC的基本概念可编程逻辑控制器(PLC)是工业自动化</div> </li> <li><a href="/article/1950232782412247040.htm" title="日更006 终极训练营day3" target="_blank">日更006 终极训练营day3</a> <span class="text-muted">懒cici</span> <div>人生创业课(2)今天的主题:学习方法一:遇到有用的书,反复读,然后结合自身实际,列践行清单,不要再写读书笔记思考这本书与我有什么关系,我在哪些地方能用到,之后我该怎么用方法二:读完书没映像怎么办?训练你的大脑,方法:每读完一遍书,立马合上书,做一场分享,几分钟都行对自己的学习要求太低,要逼自己方法三:学习深度不够怎么办?找到细分领域的榜样,把他们的文章、书籍、产品都体验一遍,成为他们的超级用户,向</div> </li> <li><a href="/article/1950232783670538240.htm" title="自律打卡第四天:比昨天进步一点点" target="_blank">自律打卡第四天:比昨天进步一点点</a> <span class="text-muted">花儿的念想</span> <div>今天新闻我们县城又确诊了一例,截止目前已经确诊的三例了,打开,看了一篇简友写的武汉的真实情况,有病住不了院,还没等到床位已经去世的消息,心里更加的难受,武汉尚且这样,如果是我们这没有高速没有火车的十八线的小县城发生这种情况,那情况将是更加的不堪设想,不敢想,唯有祈求灾难早点快去,平安才是最大的福气。突然觉得我的自律打卡,比昨天进步一点点。更希望疫情战争每一天都要比昨天好一点,希望一觉醒来听到的是好</div> </li> <li><a href="/article/1950232316408295424.htm" title="9、汇编语言编程入门:从环境搭建到简单程序实现" target="_blank">9、汇编语言编程入门:从环境搭建到简单程序实现</a> <span class="text-muted">神经网络酱</span> <a class="tag" taget="_blank" href="/search/%E6%B1%87%E7%BC%96%E8%AF%AD%E8%A8%80/1.htm">汇编语言</a><a class="tag" taget="_blank" href="/search/MEPIS/1.htm">MEPIS</a><a class="tag" taget="_blank" href="/search/GNU%E5%B7%A5%E5%85%B7%E9%93%BE/1.htm">GNU工具链</a> <div>汇编语言编程入门:从环境搭建到简单程序实现1.数据存储介质问题解决在处理数据存储时,若要使用MEPIS系统,需确保有其可访问的存储介质。目前,MEPIS无法向采用NTFS格式(常用于Windows2000和XP工作站)的硬盘写入数据。不过,若硬盘采用FAT32格式,MEPIS就能进行写入操作。此外,MEPIS还能将文件写入软盘和大多数USB闪存驱动器。若工作站连接到局域网,还可通过FTP协议或挂载</div> </li> <li><a href="/article/1950231508648259584.htm" title="三件事—小白猫·雨天·八段锦" target="_blank">三件事—小白猫·雨天·八段锦</a> <span class="text-muted">咸鱼月亮</span> <div>1.最近楼下出现一只非常漂亮的粘人小白猫,看着不像是流浪猫,非常亲人。眼睛比蓝球的还大,而且是绿色的,很漂亮。第一次遇到它,它就跟我到电梯口,如果我稍微招招手,肯定就跟我进电梯了。后来我喂过它几次,好可惜不能养它,一只蓝球就是我的极限了。2.下雨天就心烦,好奇怪。明明以前我超爱看窗外的雨和听雨声,看来近来的心情不够宁静了。3.最近在练八段锦,从第一次就爱上了这个运动,很轻松缓慢,但是却出汗。感觉可</div> </li> <li><a href="/article/1950231509906550784.htm" title="25-1-2019" target="_blank">25-1-2019</a> <span class="text-muted">树藤与海岛呢</span> <div>hello八月来报道了今天看到了一篇文章就只想记下那两句话:良田千顷不过一日三餐广夏万间只睡卧榻三尺大概的意思就是要珍惜当下不要等来不及的时候才珍惜分享今天的两餐最近没有时间运动呢下个月补回好了说完了哈哈goodnight图片发自App图片发自App</div> </li> <li><a href="/article/1950231381485350912.htm" title="《极简思维》第三部分" target="_blank">《极简思维》第三部分</a> <span class="text-muted">小洋苏兮</span> <div>整理你的人际关系如何改善人际关系?摘录:因为人际关系问题是人们生活中不快乐的主要原因。感想:感觉这个说的挺对,之前我总是埋头学习,不管舍友不管自己的合作伙伴的一些事情,但实际上,这学期关注了之后好多了摘录:“亲密关系与社交会让你健康而快乐。这是基础。太过于关注成就或不太关心人际关系的人都不怎么快乐。基本上来说,人类就是建立在人脉关系上的。”感想:但是如果有时想的太多就不太好,要以一个开放的心态跟别</div> </li> <li><a href="/article/1950231254427299840.htm" title="我不懂什么是爱,但我给你全部我拥有的" target="_blank">我不懂什么是爱,但我给你全部我拥有的</a> <span class="text-muted">香尧</span> <div>因为怕黑,所以愿意陪伴在夜中行走的人,给他一点点的安全感。因为渴望温柔与爱,所以愿意为别的孩子付出爱与温柔。因为曾遭受侮辱和伤害,所以不以同样的方式施于其他人。如果你向别人出之以利刃,对方还了你爱与包容,真的不要感激他,真的不要赞美他。每一个被人伤害过的人心里都留下了一颗仇恨的种子,他也会想要有一天以眼还眼,以牙还牙。但他未让那颗种子生根发芽,他用一把心剑又一次刺向他自己,用他血荐仇恨,开出一朵温</div> </li> <li><a href="/article/1950229418706268160.htm" title="密码正则验证:大小写字母、数字、特殊字符至少8位" target="_blank">密码正则验证:大小写字母、数字、特殊字符至少8位</a> <span class="text-muted">qq_21875331</span> <a class="tag" taget="_blank" href="/search/%E6%B8%90%E8%BF%9B%E5%BC%8F%E7%9A%84%E6%88%90%E9%95%BF/1.htm">渐进式的成长</a> <div>正则表达式:密码必须包含大写字母、数字、特殊字符(四种里至少三种,且至少8位)写法一:/((^(?=.*[a-z])(?=.*[A-Z])(?=.*\W)[\da-zA-Z\W]{8,16}$)|(^(?=.*\d)(?=.*[A-Z])(?=.*\W)[\da-zA-Z\W]{8,16}$)|(^(?=.*\d)(?=.*[a-z])(?=.*\W)[\da-zA-Z\W]{8,16}$)|(^</div> </li> <li><a href="/article/1950228031117258752.htm" title="深入解析JVM工作原理:从字节码到机器指令的全过程" target="_blank">深入解析JVM工作原理:从字节码到机器指令的全过程</a> <span class="text-muted"></span> <div>一、JVM概述Java虚拟机(JVM)是Java平台的核心组件,它实现了Java"一次编写,到处运行"的理念。JVM是一个抽象的计算机器,它有自己的指令集和运行时内存管理机制。JVM的主要职责:加载:读取.class文件并验证其正确性存储:管理内存分配和垃圾回收执行:解释或编译字节码为机器指令安全:提供沙箱环境限制恶意代码二、JVM架构详解JVM由三个主要子系统组成:1.类加载子系统类加载过程分为</div> </li> <li><a href="/article/1950228031524106240.htm" title="Spring进阶 - SpringMVC实现原理之DispatcherServlet处理请求的过程" target="_blank">Spring进阶 - SpringMVC实现原理之DispatcherServlet处理请求的过程</a> <span class="text-muted">倾听铃的声</span> <a class="tag" taget="_blank" href="/search/%E5%90%8E%E7%AB%AF/1.htm">后端</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/mvc/1.htm">mvc</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a><a class="tag" taget="_blank" href="/search/%E5%88%86%E5%B8%83%E5%BC%8F/1.htm">分布式</a> <div>前文我们有了IOC的源码基础以及SpringMVC的基础,我们便可以进一步深入理解SpringMVC主要实现原理,包含DispatcherServlet的初始化过程和DispatcherServlet处理请求的过程的源码解析。本文是第二篇:DispatcherServlet处理请求的过程的源码解析。@pdaiSpring进阶-SpringMVC实现原理之DispatcherServlet处理请求的</div> </li> <li><a href="/article/1950227023859347456.htm" title="Linux系统配置(应用程序)" target="_blank">Linux系统配置(应用程序)</a> <span class="text-muted">1风天云月</span> <a class="tag" taget="_blank" href="/search/Linux/1.htm">Linux</a><a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a><a class="tag" taget="_blank" href="/search/%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F/1.htm">应用程序</a><a class="tag" taget="_blank" href="/search/%E7%BC%96%E8%AF%91%E5%AE%89%E8%A3%85/1.htm">编译安装</a><a class="tag" taget="_blank" href="/search/rpm/1.htm">rpm</a><a class="tag" taget="_blank" href="/search/http/1.htm">http</a> <div>目录前言一、应用程序概述1、命令与程序的关系2、程序的组成3、软件包封装类型二、RPM1、RPM概述2、RPM用法三、编译安装1、解包2、配置3、编译4、安装5、启用httpd服务结语前言在Linux中的应用程序被视为将软件包安装到系统中后产生的各种文档,其中包括可执行文件、配置文件、用户手册等内容,这些文档被组织为一个有机的整体,为用户提供特定的功能,因此对于“安装软件包”与“安装应用程序”这两</div> </li> <li><a href="/article/1950226517397139456.htm" title="JVM 内存模型深度解析:原子性、可见性与有序性的实现" target="_blank">JVM 内存模型深度解析:原子性、可见性与有序性的实现</a> <span class="text-muted">练习时长两年半的程序员小胡</span> <a class="tag" taget="_blank" href="/search/JVM/1.htm">JVM</a><a class="tag" taget="_blank" href="/search/%E6%B7%B1%E5%BA%A6%E5%89%96%E6%9E%90%EF%BC%9A%E4%BB%8E%E9%9D%A2%E8%AF%95%E8%80%83%E7%82%B9%E5%88%B0%E7%94%9F%E4%BA%A7%E5%AE%9E%E8%B7%B5/1.htm">深度剖析:从面试考点到生产实践</a><a class="tag" taget="_blank" href="/search/jvm/1.htm">jvm</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B/1.htm">内存模型</a> <div>在了解了JVM的基础架构和类加载机制后,我们需要进一步探索Java程序在多线程环境下的内存交互规则。JVM内存模型(JavaMemoryModel,JMM)定义了线程和主内存之间的抽象关系,它通过规范共享变量的访问方式,解决了多线程并发时的数据一致性问题。本文将从内存模型的核心目标出发,详解原子性、可见性、有序性的实现机制,以及volatile、synchronized等关键字在其中的作用。一、J</div> </li> <li><a href="/article/1950226391064702976.htm" title="Flowable 实战落地核心:选型决策与坑点破解" target="_blank">Flowable 实战落地核心:选型决策与坑点破解</a> <span class="text-muted">练习时长两年半的程序员小胡</span> <a class="tag" taget="_blank" href="/search/Flowable/1.htm">Flowable</a><a class="tag" taget="_blank" href="/search/%E6%B5%81%E7%A8%8B%E5%BC%95%E6%93%8E%E5%AE%9E%E6%88%98%E6%8C%87%E5%8D%97/1.htm">流程引擎实战指南</a><a class="tag" taget="_blank" href="/search/%E4%BD%8E%E4%BB%A3%E7%A0%81/1.htm">低代码</a><a class="tag" taget="_blank" href="/search/BPMN/1.htm">BPMN</a><a class="tag" taget="_blank" href="/search/%E6%B5%81%E7%A8%8B%E5%BC%95%E6%93%8E/1.htm">流程引擎</a><a class="tag" taget="_blank" href="/search/flowable/1.htm">flowable</a><a class="tag" taget="_blank" href="/search/%E5%90%8E%E7%AB%AF/1.htm">后端</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a> <div>在企业级流程引擎的落地过程中,选型的准确性和坑点的预见性直接决定项目成败。本文聚焦Flowable实战中最关键的“选型决策”与“常见坑点”,结合真实项目经验,提供可落地的解决方案。一、流程引擎选型:从业务本质出发1.1选型的三大核心维度企业在选择流程引擎时,需避免陷入“技术崇拜”,应回归业务本质。评估Flowable是否适用,可从三个维度判断:业务复杂度若流程涉及动态审批链(如按金额自动升级审批)</div> </li> <li><a href="/article/1950226390070652928.htm" title="Flowable 高级扩展:自定义元素与性能优化实战" target="_blank">Flowable 高级扩展:自定义元素与性能优化实战</a> <span class="text-muted">练习时长两年半的程序员小胡</span> <a class="tag" taget="_blank" href="/search/Flowable/1.htm">Flowable</a><a class="tag" taget="_blank" href="/search/%E6%B5%81%E7%A8%8B%E5%BC%95%E6%93%8E%E5%AE%9E%E6%88%98%E6%8C%87%E5%8D%97/1.htm">流程引擎实战指南</a><a class="tag" taget="_blank" href="/search/%E6%B5%81%E7%A8%8B%E5%9B%BE/1.htm">流程图</a><a class="tag" taget="_blank" href="/search/flowable/1.htm">flowable</a><a class="tag" taget="_blank" href="/search/BPMN/1.htm">BPMN</a><a class="tag" taget="_blank" href="/search/%E6%B5%81%E7%A8%8B%E5%BC%95%E6%93%8E/1.htm">流程引擎</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a> <div>在前五篇文章中,我们从基础概念、流程设计、API实战、SpringBoot集成,到外部系统协同,逐步构建了Flowable的应用体系。但企业级复杂场景中,原生功能往往难以满足定制化需求——比如需要特殊的审批规则网关、与决策引擎联动实现动态路由,或是在高并发场景下优化流程引擎性能。本文将聚焦Flowable的高级扩展能力,详解如何自定义流程元素、集成规则引擎,并掌握大型系统中的性能调优策略。一、自定</div> </li> <li><a href="/article/1950226011559882752.htm" title="什么是缓存雪崩?缓存击穿?缓存穿透?分别如何解决?什么是缓存预热?" target="_blank">什么是缓存雪崩?缓存击穿?缓存穿透?分别如何解决?什么是缓存预热?</a> <span class="text-muted">daixin8848</span> <a class="tag" taget="_blank" href="/search/%E7%BC%93%E5%AD%98/1.htm">缓存</a><a class="tag" taget="_blank" href="/search/redis/1.htm">redis</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a> <div>缓存雪崩:在一个时间段内,有大量的key过期,或者Redis服务宕机,导致大量的请求到达数据库,带来巨大压力-给key设置不同的TTL、利用Redis集群提高服务的高可用性、添加多级缓存、添加降级流策略缓存击穿:给某一个key设置了过期时间,当key过期的时间,恰好这个时间点有大量的并发请求访问这个key,可能会瞬间把数据库压垮-互斥锁:缓存失败时,只允许一个请求去加载数据并更新缓存,其他请求阻塞</div> </li> <li><a href="/article/1950225532016717824.htm" title="恩小希美食成长日记之118:“摘星女神”王亚平归来,她的婚姻,治愈了多少职场女性的痛" target="_blank">恩小希美食成长日记之118:“摘星女神”王亚平归来,她的婚姻,治愈了多少职场女性的痛</a> <span class="text-muted">恩小希</span> <div>上周最为热闹的消息,无疑是神舟13号的三位航天英雄回来了.其中,最为瞩目的就是王亚平.她是我国首位进行太空行走的女航天员,也是为自己小女儿“摘星星的妈妈”。作为最受关注的职场妈妈,王亚平之所以能够成就这样一番事业,跟背后默默支持她的丈夫--赵鹏分不开。01王亚平1980年出生于山东烟台。父母都是地地道道的农民。王亚平这个姑娘从小体质好,一直练习长跑。高中时,空军来家乡招收女飞行员,作为体育班里唯一</div> </li> <li><a href="/article/1950225020974329856.htm" title="2019-07-30" target="_blank">2019-07-30</a> <span class="text-muted">西域社群</span> <div>天地之间,分外热闹。望热浪涛涛,引无数帅哥竞开撩,夕窈窕淑女皆露腰。一代天骄,群里热闹。不见美女露妖娆,唯见帅哥手机忙,唐诗宋词,广为流传,惜字如金,声情并茂。君悉吾析,今日之局有套路,昨日之生惹人恋。聚往矣,数风流人物还看今朝!!</div> </li> <li><a href="/article/1950224745421139968.htm" title="车载刷写架构 --- 刷写思考扩展" target="_blank">车载刷写架构 --- 刷写思考扩展</a> <span class="text-muted">汽车电子实验室</span> <a class="tag" taget="_blank" href="/search/%E7%94%B5%E5%AD%90%E7%94%B5%E5%99%A8%E6%9E%B6%E6%9E%84%E2%80%94%E2%80%94%E5%88%B7%E5%86%99%E6%96%B9%E6%A1%88/1.htm">电子电器架构——刷写方案</a><a class="tag" taget="_blank" href="/search/%E6%9E%B6%E6%9E%84/1.htm">架构</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a><a class="tag" taget="_blank" href="/search/%E5%85%B3%E4%BA%8E%E7%BD%91%E5%85%B3%E8%BD%AC%E5%8F%91%E6%80%A7%E8%83%BD%E5%BC%95%E8%B5%B7%E7%9A%84%E6%80%9D%E8%80%83/1.htm">关于网关转发性能引起的思考</a><a class="tag" taget="_blank" href="/search/%E6%B1%BD%E8%BD%A6%E4%B8%AD%E5%A4%AE%E6%8E%A7%E5%88%B6%E5%8D%95%E5%85%83HPC%E8%BD%AF%E4%BB%B6%E6%9E%B6%E6%9E%84/1.htm">汽车中央控制单元HPC软件架构</a><a class="tag" taget="_blank" href="/search/%E8%BD%A6%E8%BD%BD%E8%AF%8A%E6%96%AD%E8%BF%9B%E9%98%B6%E7%AF%87/1.htm">车载诊断进阶篇</a> <div>我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师:做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从,不跟风。把自己的精力全部用在自己。一是去掉多余,凡事找规律,基础是诚信;二是系统思考、大胆设计、小心求证;三是“一张纸制度”,也就是无论多么复杂的工作内容,要在一张纸上描述清楚;四是要坚决反对虎头蛇尾,反对繁文缛节,反对老</div> </li> <li><a href="/article/1950223244883718144.htm" title="上半年居民消费榜出炉!这个城市的人最能花" target="_blank">上半年居民消费榜出炉!这个城市的人最能花</a> <span class="text-muted">BBM优选官方</span> <div>上半年居民消费榜出炉哪个地方的人最能花钱?国家统计局公布的数据显示上海上半年居民人均可支配收入32612元居民人均消费支出21321元均为全国最高成为最能挣钱也最能花钱的城市1上海人均消费支出全国第一国家统计局公布的31省份居民人均消费支出数据显示,上海、北京、天津上半年居民人均消费支出排名前三。其中,上海上半年居民人均消费支出21321元,位居榜首。上海也是上半年全国仅有的居民人均消费支出突破2</div> </li> <li><a href="/article/1950222094314827776.htm" title="【老房翻新】92平轻奢简约风,将和谐之美融入空间!" target="_blank">【老房翻新】92平轻奢简约风,将和谐之美融入空间!</a> <span class="text-muted">没人比我更懂装修</span> <div>在客厅空间中,设计师于冷静的空间基调中选用了层次感丰富的黄蓝色作为主要跳色,搭配黑白纹理的地毯与单椅,为空间增加了时尚摩登的气息。艺术感的单品突出点亮了空间,绿植的点缀、留白的软饰则增强了空间的呼吸性。点击此处添加图片说明文字点击此处添加图片说明文字设计师力求使每一处的设立都在空间中达到相互间的呼应与制衡,将艺术的跃动之美赋于空间之上,也将空间的和谐之美融于生活之中。点击此处添加图片说明文字点击此</div> </li> <li><a href="/article/1950221840026759168.htm" title="漫游漫川关" target="_blank">漫游漫川关</a> <span class="text-muted">高曾骏骏</span> <div>傍晚时分,夕阳从树的缝隙穿过来撒在我们老老小小一家人身上暖暖的,一抬头映入眼帘的是“朝秦暮楚”四个字挂在山壁上,我知道漫川关到了。90岁的老爸在前面慢悠悠的走着,用浓郁的河南话问正在赶路的几个老人家,:“你们是哪里人呀?”其中一个扛着锄头的老人家声如洪钟的答到:“我们是祖祖辈辈生活在这里的漫川关人。你是河南人吧?”看着老爸点点头老人家继续说,“这里可是一鸡鸣三省的地方,河南,陕西,湖北交界处”。老</div> </li> <li><a href="/article/1950221332746661888.htm" title="学生把我的课件换成小三认罪书(赵书晴宋诗月)全集阅读_学生把我的课件换成小三认罪书最新章节阅读_赵书晴宋诗月(学生把我的课件换成小三认罪书)全本免费在线阅读_(学生把我的课件换成小三认罪书)完结..." target="_blank">学生把我的课件换成小三认罪书(赵书晴宋诗月)全集阅读_学生把我的课件换成小三认罪书最新章节阅读_赵书晴宋诗月(学生把我的课件换成小三认罪书)全本免费在线阅读_(学生把我的课件换成小三认罪书)完结...</a> <span class="text-muted">笔趣阁热门小说</span> <div>学生把我的课件换成小三认罪书(赵书晴宋诗月)全集阅读_学生把我的课件换成小三认罪书最新章节阅读_赵书晴宋诗月(学生把我的课件换成小三认罪书)全本免费在线阅读_(学生把我的课件换成小三认罪书)完结版免费在线阅读_学生把我的课件换成小三认罪书(赵书晴宋诗月)完整版免费阅读_(学生把我的课件换成小三认罪书)全章节免费在线阅读主角配角:赵书晴宋诗月简介:我和赵京立去了民政局提交了申请因为离婚冷静期,还要再</div> </li> <li><a href="/article/1950219924043526144.htm" title="二十四节气组诗 谷雨" target="_blank">二十四节气组诗 谷雨</a> <span class="text-muted">离陌_6639</span> <div>图片来源网络,若侵犯了你的权益,请联系我删除6.谷雨文/离陌背上行囊背上如行囊的我从此任行程马不停蹄今天家乡的田野春雨快马加鞭播下希望的种子观音不语目送着我和夏天一道在观音山出关图片来源网络,若侵犯了你的权益,请联系我删除你好啊,我是离陌,已然在懵懂中走过了16年的岁月,为了珍惜当下的每一秒,所以立志做一名终身学习者。文学对于我来说是一种信仰,诗歌是我的生命。人生之道,四通八达,即入文学,自当持之</div> </li> <li><a href="/article/1950218399846035456.htm" title="营销活动-大转盘" target="_blank">营销活动-大转盘</a> <span class="text-muted">無缺520</span> <div>写在前面最近,首先营销活动工具这块我是再熟悉不过了。曾经做了不下20个活动工具,然后通过监控活动数据反推活动的好坏。文中主要讲解幸运大转盘营销工具一.大转盘定义大转盘是比较常见的营销活动工具,它是通过消费者用户控制【开始/停止】操作获得奖品物品。用户在不知道自己能获得什么奖品的条件下,然后通过抽奖,大概率的获得未知的奖品。类似最近流行的盲盒玩法。二.为什么做大转盘大转盘是最常用的抽奖类的活动工具之</div> </li> <li><a href="/article/1950218314064130048.htm" title="Java并发核心:线程池使用技巧与最佳实践! | 多线程篇(五)" target="_blank">Java并发核心:线程池使用技巧与最佳实践! | 多线程篇(五)</a> <span class="text-muted">bug菌¹</span> <a class="tag" taget="_blank" href="/search/Java%E5%AE%9E%E6%88%98%28%E8%BF%9B%E9%98%B6%E7%89%88%29/1.htm">Java实战(进阶版)</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/Java%E9%9B%B6%E5%9F%BA%E7%A1%80%E5%85%A5%E9%97%A8/1.htm">Java零基础入门</a><a class="tag" taget="_blank" href="/search/Java%E5%B9%B6%E5%8F%91/1.htm">Java并发</a><a class="tag" taget="_blank" href="/search/%E7%BA%BF%E7%A8%8B%E6%B1%A0/1.htm">线程池</a><a class="tag" taget="_blank" href="/search/%E5%A4%9A%E7%BA%BF%E7%A8%8B%E7%AF%87/1.htm">多线程篇</a> <div>本文收录于「Java进阶实战」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!环境说明:Windows10+IntelliJIDEA2021.3.2+Jdk1.8本文目录前言摘要正文何为线程池?为什么需要线程池?线程池的好处线程池使用场景如何创建线程池?线程池的常见配置源码解析案例分享案例代码演示案例运行</div> </li> <li><a href="/article/1950218019712069632.htm" title="承德十大亲子鉴定医院名单(附2024年10所正规医院)" target="_blank">承德十大亲子鉴定医院名单(附2024年10所正规医院)</a> <span class="text-muted">国医基因陈主任</span> <div>承德哪家医院可以做亲子鉴定?承德市中心医院、中国人民解放军第二六六医院、承德医学院附属医院等都可以做常规亲子鉴定采样采集,一般的医院并不可以为你提供常规亲子鉴定检测的服务。承德亲子鉴定中心地址:承德市西大街路北11号(承德国医基因)。一般只有少数三甲医院可以做亲子鉴定采样,或者当地亲子鉴定中心可以做亲子鉴定。如果想做亲子鉴定,最好直接到亲子鉴定中心内或亲子鉴定医院采样点内进行双方抽血鉴定,这样会更</div> </li> <li><a href="/article/1950217889994829824.htm" title="践行8.0~第六周11.25-12.02" target="_blank">践行8.0~第六周11.25-12.02</a> <span class="text-muted">初队长</span> <div>突破后的喜悦最可怕的不是自己不清楚,而是自己清楚了,却依然不心动,我想这就是我们每个人的惰性存在,在这一周的践行,我发现自己依然是停留在自己的模式当中,不断的恶性的轮回,虽然的话,那再晨间日记方面是纸质的填写,但是对一天的工作没有起到应有的计划和推动的作用而我自己呢,也有些时候的话会处于一个相对来讲放松的一个状态,时间的把控的话也有一些点的消极,所以在这周的间隙,重点是关注自己的三大目标为目标来进</div> </li> <li><a href="/article/1950217304876838912.htm" title="STM32入门之TIM基本定时器" target="_blank">STM32入门之TIM基本定时器</a> <span class="text-muted">嵌入式白话</span> <a class="tag" taget="_blank" href="/search/STM32%E5%85%A5%E9%97%A8%E5%AD%A6%E4%B9%A0/1.htm">STM32入门学习</a><a class="tag" taget="_blank" href="/search/stm32/1.htm">stm32</a><a class="tag" taget="_blank" href="/search/%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%A1%AC%E4%BB%B6/1.htm">嵌入式硬件</a><a class="tag" taget="_blank" href="/search/%E5%8D%95%E7%89%87%E6%9C%BA/1.htm">单片机</a> <div>一、定时器简介定时器是嵌入式系统中的关键外设之一,它可以用于生成精确的延时、周期性中断、PWM波形生成等功能。在STM32F1系列单片机中,定时器不仅能为系统提供精确的时钟,还支持外部事件的捕获以及信号输出。对于定时器的功能,我们可以通过一个生活中非常常见的例子来形象地描述:微波炉的定时器。想象你正在使用微波炉加热食物。在微波炉里,定时器的作用就是帮助你控制食物加热的时间。当你设置了加热时间后,定</div> </li> <li><a href="/article/19.htm" title="解线性方程组" target="_blank">解线性方程组</a> <span class="text-muted">qiuwanchi</span> <div>package gaodai.matrix; import java.util.ArrayList; import java.util.List; import java.util.Scanner; public class Test { public static void main(String[] args) { Scanner scanner = new Sc</div> </li> <li><a href="/article/146.htm" title="在mysql内部存储代码" target="_blank">在mysql内部存储代码</a> <span class="text-muted">annan211</span> <a class="tag" taget="_blank" href="/search/%E6%80%A7%E8%83%BD/1.htm">性能</a><a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a><a class="tag" taget="_blank" href="/search/%E5%AD%98%E5%82%A8%E8%BF%87%E7%A8%8B/1.htm">存储过程</a><a class="tag" taget="_blank" href="/search/%E8%A7%A6%E5%8F%91%E5%99%A8/1.htm">触发器</a> <div> 在mysql内部存储代码 在mysql内部存储代码,既有优点也有缺点,而且有人倡导有人反对。 先看优点: 1 她在服务器内部执行,离数据最近,另外在服务器上执行还可以节省带宽和网络延迟。 2 这是一种代码重用。可以方便的统一业务规则,保证某些行为的一致性,所以也可以提供一定的安全性。 3 可以简化代码的维护和版本更新。 4 可以帮助提升安全,比如提供更细</div> </li> <li><a href="/article/273.htm" title="Android使用Asynchronous Http Client完成登录保存cookie的问题" target="_blank">Android使用Asynchronous Http Client完成登录保存cookie的问题</a> <span class="text-muted">hotsunshine</span> <a class="tag" taget="_blank" href="/search/android/1.htm">android</a> <div>Asynchronous Http Client是android中非常好的异步请求工具 除了异步之外还有很多封装比如json的处理,cookie的处理 引用 Persistent Cookie Storage with PersistentCookieStore This library also includes a PersistentCookieStore whi</div> </li> <li><a href="/article/400.htm" title="java面试题" target="_blank">java面试题</a> <span class="text-muted">Array_06</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E9%9D%A2%E8%AF%95/1.htm">面试</a> <div>java面试题 第一,谈谈final, finally, finalize的区别。 final-修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承。因此一个类不能既被声明为 abstract的,又被声明为final的。将变量或方法声明为final,可以保证它们在使用中不被改变。被声明为final的变量必须在声明时给定初值,而在以后的引用中只能</div> </li> <li><a href="/article/527.htm" title="网站加速" target="_blank">网站加速</a> <span class="text-muted">oloz</span> <a class="tag" taget="_blank" href="/search/%E7%BD%91%E7%AB%99%E5%8A%A0%E9%80%9F/1.htm">网站加速</a> <div>前序:本人菜鸟,此文研究总结来源于互联网上的资料,大牛请勿喷!本人虚心学习,多指教. 1、减小网页体积的大小,尽量采用div+css模式,尽量避免复杂的页面结构,能简约就简约。 2、采用Gzip对网页进行压缩;    GZIP最早由Jean-loup Gailly和Mark Adler创建,用于UNⅨ系统的文件压缩。我们在Linux中经常会用到后缀为.gz</div> </li> <li><a href="/article/654.htm" title="正确书写单例模式" target="_blank">正确书写单例模式</a> <span class="text-muted">随意而生</span> <a class="tag" taget="_blank" href="/search/java+%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F+%E5%8D%95%E4%BE%8B/1.htm">java 设计模式 单例</a> <div>  单例模式算是设计模式中最容易理解,也是最容易手写代码的模式了吧。但是其中的坑却不少,所以也常作为面试题来考。本文主要对几种单例写法的整理,并分析其优缺点。很多都是一些老生常谈的问题,但如果你不知道如何创建一个线程安全的单例,不知道什么是双检锁,那这篇文章可能会帮助到你。   懒汉式,线程不安全   当被问到要实现一个单例模式时,很多人的第一反应是写出如下的代码,包括教科书上也是这样</div> </li> <li><a href="/article/781.htm" title="单例模式" target="_blank">单例模式</a> <span class="text-muted">香水浓</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a> <div>懒汉  调用getInstance方法时实例化 public class Singleton { private static Singleton instance; private Singleton() {} public static synchronized Singleton getInstance() { if(null == ins</div> </li> <li><a href="/article/908.htm" title="安装Apache问题:系统找不到指定的文件 No installed service named "Apache2"" target="_blank">安装Apache问题:系统找不到指定的文件 No installed service named "Apache2"</a> <span class="text-muted">AdyZhang</span> <a class="tag" taget="_blank" href="/search/apache/1.htm">apache</a><a class="tag" taget="_blank" href="/search/http+server/1.htm">http server</a> <div>安装Apache问题:系统找不到指定的文件 No installed service named "Apache2" 每次到这一步都很小心防它的端口冲突问题,结果,特意留出来的80端口就是不能用,烦。 解决方法确保几处: 1、停止IIS启动 2、把端口80改成其它 (譬如90,800,,,什么数字都好) 3、防火墙(关掉试试) 在运行处输入 cmd 回车,转到apa</div> </li> <li><a href="/article/1035.htm" title="如何在android 文件选择器中选择多个图片或者视频?" target="_blank">如何在android 文件选择器中选择多个图片或者视频?</a> <span class="text-muted">aijuans</span> <a class="tag" taget="_blank" href="/search/android/1.htm">android</a> <div>我的android app有这样的需求,在进行照片和视频上传的时候,需要一次性的从照片/视频库选择多条进行上传 但是android原生态的sdk中,只能一个一个的进行选择和上传。 我想知道是否有其他的android上传库可以解决这个问题,提供一个多选的功能,可以使checkbox之类的,一次选择多个 处理方法 官方的图片选择器(但是不支持所有版本的androi,只支持API Level </div> </li> <li><a href="/article/1162.htm" title="mysql中查询生日提醒的日期相关的sql" target="_blank">mysql中查询生日提醒的日期相关的sql</a> <span class="text-muted">baalwolf</span> <a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a> <div>SELECT sysid,user_name,birthday,listid,userhead_50,CONCAT(YEAR(CURDATE()),DATE_FORMAT(birthday,'-%m-%d')),CURDATE(),  dayofyear( CONCAT(YEAR(CURDATE()),DATE_FORMAT(birthday,'-%m-%d')))-dayofyear(</div> </li> <li><a href="/article/1289.htm" title="MongoDB索引文件破坏后导致查询错误的问题" target="_blank">MongoDB索引文件破坏后导致查询错误的问题</a> <span class="text-muted">BigBird2012</span> <a class="tag" taget="_blank" href="/search/mongodb/1.htm">mongodb</a> <div>问题描述: MongoDB在非正常情况下关闭时,可能会导致索引文件破坏,造成数据在更新时没有反映到索引上。 解决方案:   使用脚本,重建MongoDB所有表的索引。 var names = db.getCollectionNames(); for( var i in names ){ var name = names[i]; print(name); </div> </li> <li><a href="/article/1416.htm" title="Javascript Promise" target="_blank">Javascript Promise</a> <span class="text-muted">bijian1013</span> <a class="tag" taget="_blank" href="/search/JavaScript/1.htm">JavaScript</a><a class="tag" taget="_blank" href="/search/Promise/1.htm">Promise</a> <div>        Parse JavaScript SDK现在提供了支持大多数异步方法的兼容jquery的Promises模式,那么这意味着什么呢,读完下文你就了解了。 一.认识Promises         “Promises”代表着在javascript程序里下一个伟大的范式,但是理解他们为什么如此伟大不是件简</div> </li> <li><a href="/article/1543.htm" title="[Zookeeper学习笔记九]Zookeeper源代码分析之Zookeeper构造过程" target="_blank">[Zookeeper学习笔记九]Zookeeper源代码分析之Zookeeper构造过程</a> <span class="text-muted">bit1129</span> <a class="tag" taget="_blank" href="/search/zookeeper/1.htm">zookeeper</a> <div>   Zookeeper重载了几个构造函数,其中构造者可以提供参数最多,可定制性最多的构造函数是     public ZooKeeper(String connectString, int sessionTimeout, Watcher watcher, long sessionId, byte[] sessionPasswd, boolea</div> </li> <li><a href="/article/1670.htm" title="【Java命令三】jstack" target="_blank">【Java命令三】jstack</a> <span class="text-muted">bit1129</span> <a class="tag" taget="_blank" href="/search/jstack/1.htm">jstack</a> <div>jstack是用于获得当前运行的Java程序所有的线程的运行情况(thread dump),不同于jmap用于获得memory dump   [hadoop@hadoop sbin]$ jstack Usage: jstack [-l] <pid> (to connect to running process) jstack -F </div> </li> <li><a href="/article/1797.htm" title="jboss 5.1启停脚本 动静分离部署" target="_blank">jboss 5.1启停脚本 动静分离部署</a> <span class="text-muted">ronin47</span> <div>以前启动jboss,往各种xml配置文件,现只要运行一句脚本即可。start nohup sh /**/run.sh -c servicename  -b ip -g  clustername   -u broatcast jboss.messaging.ServerPeerID=int  -Djboss.service.binding.set=p</div> </li> <li><a href="/article/1924.htm" title="UI之如何打磨设计能力?" target="_blank">UI之如何打磨设计能力?</a> <span class="text-muted">brotherlamp</span> <a class="tag" taget="_blank" href="/search/UI/1.htm">UI</a><a class="tag" taget="_blank" href="/search/ui%E6%95%99%E7%A8%8B/1.htm">ui教程</a><a class="tag" taget="_blank" href="/search/ui%E8%87%AA%E5%AD%A6/1.htm">ui自学</a><a class="tag" taget="_blank" href="/search/ui%E8%B5%84%E6%96%99/1.htm">ui资料</a><a class="tag" taget="_blank" href="/search/ui%E8%A7%86%E9%A2%91/1.htm">ui视频</a> <div>  在越来越拥挤的初创企业世界里,视觉设计的重要性往往可以与杀手级用户体验比肩。在许多情况下,尤其对于 Web 初创企业而言,这两者都是不可或缺的。前不久我们在《右脑革命:别学编程了,学艺术吧》中也曾发出过重视设计的呼吁。如何才能提高初创企业的设计能力呢?以下是 9 位创始人的体会。 1.找到自己的方式 如果你是设计师,要想提高技能可以去设计博客和展示好设计的网站如D-lists或</div> </li> <li><a href="/article/2051.htm" title="三色旗算法" target="_blank">三色旗算法</a> <span class="text-muted">bylijinnan</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a> <div> import java.util.Arrays; /** 问题: 假设有一条绳子,上面有红、白、蓝三种颜色的旗子,起初绳子上的旗子颜色并没有顺序, 您希望将之分类,并排列为蓝、白、红的顺序,要如何移动次数才会最少,注意您只能在绳 子上进行这个动作,而且一次只能调换两个旗子。 网上的解法大多类似: 在一条绳子上移动,在程式中也就意味只能使用一个阵列,而不使用其它的阵列来</div> </li> <li><a href="/article/2178.htm" title="警告:No configuration found for the specified action: \'s" target="_blank">警告:No configuration found for the specified action: \'s</a> <span class="text-muted">chiangfai</span> <a class="tag" taget="_blank" href="/search/configuration/1.htm">configuration</a> <div>1.index.jsp页面form标签未指定namespace属性。 <!--index.jsp代码--> <%@taglib prefix="s" uri="/struts-tags"%> ... <s:form action="submit" method="post"&g</div> </li> <li><a href="/article/2305.htm" title="redis -- hash_max_zipmap_entries设置过大有问题" target="_blank">redis -- hash_max_zipmap_entries设置过大有问题</a> <span class="text-muted">chenchao051</span> <a class="tag" taget="_blank" href="/search/redis/1.htm">redis</a><a class="tag" taget="_blank" href="/search/hash/1.htm">hash</a> <div>使用redis时为了使用hash追求更高的内存使用率,我们一般都用hash结构,并且有时候会把hash_max_zipmap_entries这个值设置的很大,很多资料也推荐设置到1000,默认设置为了512,但是这里有个坑   #define ZIPMAP_BIGLEN 254 #define ZIPMAP_END 255     /* Return th</div> </li> <li><a href="/article/2432.htm" title="select into outfile access deny问题" target="_blank">select into outfile access deny问题</a> <span class="text-muted">daizj</span> <a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a><a class="tag" taget="_blank" href="/search/txt/1.htm">txt</a><a class="tag" taget="_blank" href="/search/%E5%AF%BC%E5%87%BA%E6%95%B0%E6%8D%AE%E5%88%B0%E6%96%87%E4%BB%B6/1.htm">导出数据到文件</a> <div>本文转自:http://hatemysql.com/2010/06/29/select-into-outfile-access-deny%E9%97%AE%E9%A2%98/ 为应用建立了rnd的帐号,专门为他们查询线上数据库用的,当然,只有他们上了生产网络以后才能连上数据库,安全方面我们还是很注意的,呵呵。 授权的语句如下: grant select on armory.* to rn</div> </li> <li><a href="/article/2559.htm" title="phpexcel导出excel表简单入门示例" target="_blank">phpexcel导出excel表简单入门示例</a> <span class="text-muted">dcj3sjt126com</span> <a class="tag" taget="_blank" href="/search/PHP/1.htm">PHP</a><a class="tag" taget="_blank" href="/search/Excel/1.htm">Excel</a><a class="tag" taget="_blank" href="/search/phpexcel/1.htm">phpexcel</a> <div> <?php error_reporting(E_ALL); ini_set('display_errors', TRUE); ini_set('display_startup_errors', TRUE);   if (PHP_SAPI == 'cli') die('This example should only be run from a Web Brows</div> </li> <li><a href="/article/2686.htm" title="美国电影超短200句" target="_blank">美国电影超短200句</a> <span class="text-muted">dcj3sjt126com</span> <a class="tag" taget="_blank" href="/search/%E7%94%B5%E5%BD%B1/1.htm">电影</a> <div>1. I see. 我明白了。2. I quit! 我不干了!3. Let go! 放手!4. Me too. 我也是。5. My god! 天哪!6. No way! 不行!7. Come on. 来吧(赶快)8. Hold on. 等一等。9. I agree。 我同意。10. Not bad. 还不错。11. Not yet. 还没。12. See you. 再见。13. Shut up! </div> </li> <li><a href="/article/2813.htm" title="Java访问远程服务" target="_blank">Java访问远程服务</a> <span class="text-muted">dyy_gusi</span> <a class="tag" taget="_blank" href="/search/httpclient/1.htm">httpclient</a><a class="tag" taget="_blank" href="/search/webservice/1.htm">webservice</a><a class="tag" taget="_blank" href="/search/get/1.htm">get</a><a class="tag" taget="_blank" href="/search/post/1.htm">post</a> <div>    随着webService的崛起,我们开始中会越来越多的使用到访问远程webService服务。当然对于不同的webService框架一般都有自己的client包供使用,但是如果使用webService框架自己的client包,那么必然需要在自己的代码中引入它的包,如果同时调运了多个不同框架的webService,那么就需要同时引入多个不同的clien</div> </li> <li><a href="/article/2940.htm" title="Maven的settings.xml配置" target="_blank">Maven的settings.xml配置</a> <span class="text-muted">geeksun</span> <a class="tag" taget="_blank" href="/search/settings.xml/1.htm">settings.xml</a> <div>settings.xml是Maven的配置文件,下面解释一下其中的配置含义: settings.xml存在于两个地方: 1.安装的地方:$M2_HOME/conf/settings.xml 2.用户的目录:${user.home}/.m2/settings.xml 前者又被叫做全局配置,后者被称为用户配置。如果两者都存在,它们的内容将被合并,并且用户范围的settings.xml优先。 </div> </li> <li><a href="/article/3067.htm" title="ubuntu的init与系统服务设置" target="_blank">ubuntu的init与系统服务设置</a> <span class="text-muted">hongtoushizi</span> <a class="tag" taget="_blank" href="/search/ubuntu/1.htm">ubuntu</a> <div>转载自:  http://iysm.net/?p=178 init Init是位于/sbin/init的一个程序,它是在linux下,在系统启动过程中,初始化所有的设备驱动程序和数据结构等之后,由内核启动的一个用户级程序,并由此init程序进而完成系统的启动过程。 ubuntu与传统的linux略有不同,使用upstart完成系统的启动,但表面上仍维持init程序的形式。 运行</div> </li> <li><a href="/article/3194.htm" title="跟我学Nginx+Lua开发目录贴" target="_blank">跟我学Nginx+Lua开发目录贴</a> <span class="text-muted">jinnianshilongnian</span> <a class="tag" taget="_blank" href="/search/nginx/1.htm">nginx</a><a class="tag" taget="_blank" href="/search/lua/1.htm">lua</a> <div>使用Nginx+Lua开发近一年的时间,学习和实践了一些Nginx+Lua开发的架构,为了让更多人使用Nginx+Lua架构开发,利用春节期间总结了一份基本的学习教程,希望对大家有用。也欢迎谈探讨学习一些经验。    目录 第一章 安装Nginx+Lua开发环境 第二章 Nginx+Lua开发入门 第三章 Redis/SSDB+Twemproxy安装与使用 第四章 L</div> </li> <li><a href="/article/3321.htm" title="php位运算符注意事项" target="_blank">php位运算符注意事项</a> <span class="text-muted">home198979</span> <a class="tag" taget="_blank" href="/search/%E4%BD%8D%E8%BF%90%E7%AE%97/1.htm">位运算</a><a class="tag" taget="_blank" href="/search/PHP/1.htm">PHP</a><a class="tag" taget="_blank" href="/search/%26/1.htm">&</a> <div>$a = $b = $c = 0; $a & $b = 1; $b | $c = 1  问a,b,c最终为多少?   当看到这题时,我犯了一个低级错误,误 以为位运算符会改变变量的值。所以得出结果是1 1 0 但是位运算符是不会改变变量的值的,例如: $a=1;$b=2; $a&$b;  这样a,b的值不会有任何改变 </div> </li> <li><a href="/article/3448.htm" title="Linux shell数组建立和使用技巧" target="_blank">Linux shell数组建立和使用技巧</a> <span class="text-muted">pda158</span> <a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a> <div>1.数组定义   [chengmo@centos5 ~]$ a=(1 2 3 4 5)   [chengmo@centos5 ~]$ echo $a   1   一对括号表示是数组,数组元素用“空格”符号分割开。    2.数组读取与赋值   得到长度:   [chengmo@centos5 ~]$ echo ${#a[@]}   5   用${#数组名[@或</div> </li> <li><a href="/article/3575.htm" title="hotspot源码(JDK7)" target="_blank">hotspot源码(JDK7)</a> <span class="text-muted">ol_beta</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/HotSpot/1.htm">HotSpot</a><a class="tag" taget="_blank" href="/search/jvm/1.htm">jvm</a> <div>源码结构图,方便理解:   ├─agent                            Serviceab</div> </li> <li><a href="/article/3702.htm" title="Oracle基本事务和ForAll执行批量DML练习" target="_blank">Oracle基本事务和ForAll执行批量DML练习</a> <span class="text-muted">vipbooks</span> <a class="tag" taget="_blank" href="/search/oracle/1.htm">oracle</a><a class="tag" taget="_blank" href="/search/sql/1.htm">sql</a> <div>基本事务的使用: 从账户一的余额中转100到账户二的余额中去,如果账户二不存在或账户一中的余额不足100则整笔交易回滚 select * from account; -- 创建一张账户表 create table account( -- 账户ID id number(3) not null, -- 账户名称 nam</div> </li> </ul> </div> </div> </div> <div> <div class="container"> <div class="indexes"> <strong>按字母分类:</strong> <a href="/tags/A/1.htm" target="_blank">A</a><a href="/tags/B/1.htm" target="_blank">B</a><a href="/tags/C/1.htm" target="_blank">C</a><a href="/tags/D/1.htm" target="_blank">D</a><a href="/tags/E/1.htm" target="_blank">E</a><a href="/tags/F/1.htm" target="_blank">F</a><a href="/tags/G/1.htm" target="_blank">G</a><a href="/tags/H/1.htm" target="_blank">H</a><a href="/tags/I/1.htm" target="_blank">I</a><a href="/tags/J/1.htm" target="_blank">J</a><a href="/tags/K/1.htm" target="_blank">K</a><a href="/tags/L/1.htm" target="_blank">L</a><a href="/tags/M/1.htm" target="_blank">M</a><a href="/tags/N/1.htm" target="_blank">N</a><a href="/tags/O/1.htm" target="_blank">O</a><a href="/tags/P/1.htm" target="_blank">P</a><a href="/tags/Q/1.htm" target="_blank">Q</a><a href="/tags/R/1.htm" target="_blank">R</a><a href="/tags/S/1.htm" target="_blank">S</a><a href="/tags/T/1.htm" target="_blank">T</a><a href="/tags/U/1.htm" target="_blank">U</a><a href="/tags/V/1.htm" target="_blank">V</a><a href="/tags/W/1.htm" target="_blank">W</a><a href="/tags/X/1.htm" target="_blank">X</a><a href="/tags/Y/1.htm" target="_blank">Y</a><a href="/tags/Z/1.htm" target="_blank">Z</a><a href="/tags/0/1.htm" target="_blank">其他</a> </div> </div> </div> <footer id="footer" class="mb30 mt30"> <div class="container"> <div class="footBglm"> <a target="_blank" href="/">首页</a> - <a target="_blank" href="/custom/about.htm">关于我们</a> - <a target="_blank" href="/search/Java/1.htm">站内搜索</a> - <a target="_blank" href="/sitemap.txt">Sitemap</a> - <a target="_blank" href="/custom/delete.htm">侵权投诉</a> </div> <div class="copyright">版权所有 IT知识库 CopyRight © 2000-2050 E-COM-NET.COM , All Rights Reserved. <!-- <a href="https://beian.miit.gov.cn/" rel="nofollow" target="_blank">京ICP备09083238号</a><br>--> </div> </div> </footer> <!-- 代码高亮 --> <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shCore.js"></script> <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shLegacy.js"></script> <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shAutoloader.js"></script> <link type="text/css" rel="stylesheet" href="/static/syntaxhighlighter/styles/shCoreDefault.css"/> <script type="text/javascript" src="/static/syntaxhighlighter/src/my_start_1.js"></script> </body> </html>