-
Notifications
You must be signed in to change notification settings - Fork 0
/
local-search.xml
49 lines (23 loc) · 30.2 KB
/
local-search.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>Java线程相关的常用方法</title>
<link href="/2021/07/11/Java%E7%BA%BF%E7%A8%8B%E7%9B%B8%E5%85%B3%E7%9A%84%E5%B8%B8%E7%94%A8%E6%96%B9%E6%B3%95/"/>
<url>/2021/07/11/Java%E7%BA%BF%E7%A8%8B%E7%9B%B8%E5%85%B3%E7%9A%84%E5%B8%B8%E7%94%A8%E6%96%B9%E6%B3%95/</url>
<content type="html"><![CDATA[<h1 id="1-start和run方法"><a href="#1-start和run方法" class="headerlink" title="1 start和run方法"></a>1 start和run方法</h1><p>new一个<code>Thread</code>,线程进入了新建状态。调用<code>start()</code>方法,会启动一个线程并使线程进入了就绪状态,当分配到时间片后就可以开始运行了。<code>start()</code>会执行线程的相应准备工作,然后自动执行<code>run()</code>方法的内容,这是真正的多线程工作。 但是,直接执行 <code>run()</code> 方法,会把 <code>run()</code> 方法当成一个 main 线程下的普通方法去执行,并不会在某个线程中执行它,所以这并不是多线程工作。</p><blockquote><p><strong>调用<code>start()</code>方法方可启动线程并使线程进入就绪状态,直接执行<code>run()</code>方法的话不会以多线程的方式执行。</strong></p></blockquote><h1 id="2-sleep方法"><a href="#2-sleep方法" class="headerlink" title="2 sleep方法"></a>2 sleep方法</h1><ol><li>调用 <code>sleep</code> 会让当前线程从 <strong>Running 进入 Timed Waiting 状态(阻塞)</strong>,让出指定时间的CPU执行权,该段时间内不再参与CPU调度,但线程拥有的监视器资源不会被释放,比如持有的锁;</li><li>睡眠时间到了之后,会进入到就绪状态,等待CPU分配时间段执行;</li><li>其它线程可以使用**<code>interrupt</code>** 方法打断正在睡眠的线程,这时 sleep 方法会抛出<code>InterruptedException</code>。</li></ol><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><code class="hljs csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">SleepTest01</span> {<br> <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> final Lock <span class="hljs-keyword">lock</span> = <span class="hljs-keyword">new</span> ReentrantLock();<br><br> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span>(<span class="hljs-params">String[] args</span>)</span> {<br> <span class="hljs-comment">// 线程A</span><br> Thread threadA = <span class="hljs-keyword">new</span> Thread(() -> {<br> <span class="hljs-comment">// 获取独占锁</span><br> <span class="hljs-keyword">lock</span>.<span class="hljs-keyword">lock</span>();<br> <span class="hljs-keyword">try</span> {<br> System.<span class="hljs-keyword">out</span>.println(<span class="hljs-string">"Thread A is in sleep"</span>);<br> Thread.sleep(<span class="hljs-number">2500</span>);<br> System.<span class="hljs-keyword">out</span>.println(<span class="hljs-string">"Thread A is in awaked"</span>);<br> } catch (InterruptedException e) {<br> e.printStackTrace();<br> } <span class="hljs-keyword">finally</span> {<br> <span class="hljs-keyword">lock</span>.unlock();<br> }<br> });<br><br> <span class="hljs-comment">// 线程B</span><br> Thread threadB = <span class="hljs-keyword">new</span> Thread(() -> {<br> <span class="hljs-comment">// 获取独占锁</span><br> <span class="hljs-keyword">lock</span>.<span class="hljs-keyword">lock</span>();<br> <span class="hljs-keyword">try</span> {<br> System.<span class="hljs-keyword">out</span>.println(<span class="hljs-string">"Thread B is in sleep"</span>);<br> Thread.sleep(<span class="hljs-number">2500</span>);<br> System.<span class="hljs-keyword">out</span>.println(<span class="hljs-string">"Thread B is in awaked"</span>);<br> } catch (InterruptedException e) {<br> e.printStackTrace();<br> } <span class="hljs-keyword">finally</span> {<br> <span class="hljs-keyword">lock</span>.unlock();<br> }<br> });<br><br> threadA.start();<br> threadB.start();<br> }<br>}<br></code></pre></td></tr></table></figure><p>以上代码无论执行多少次,总是A或者B先执行,并不会出现A和B交替运行的情况。</p><p>下面的代码演示了子线程在睡眠期间被主线程打断的情况:</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SleepTest02</span> </span>{<br> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> <span class="hljs-keyword">throws</span> InterruptedException </span>{<br> Thread thread = <span class="hljs-keyword">new</span> Thread(() -> {<br> <span class="hljs-keyword">try</span> {<br> System.out.println(<span class="hljs-string">"Sub thread is in sleep"</span>);<br> Thread.sleep(<span class="hljs-number">5000</span>);<br> System.out.println(<span class="hljs-string">"Sub thread is in awaked"</span>);<br> } <span class="hljs-keyword">catch</span> (InterruptedException e) {<br> e.printStackTrace();<br> }<br> });<br> thread.start(); <span class="hljs-comment">// 子线程执行</span><br> Thread.sleep(<span class="hljs-number">2000</span>); <span class="hljs-comment">// 主线程睡眠2000ms</span><br> thread.interrupt(); <span class="hljs-comment">// 终端子线程</span><br> }<br>}<br></code></pre></td></tr></table></figure><p>其执行结果如下:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs bash">Sub thread is <span class="hljs-keyword">in</span> sleep<br>java.lang.InterruptedException: sleep interrupted<br>at java.base/java.lang.Thread.sleep(Native Method)<br>at cn.tgq007.sleep.SleepTest02.lambda$main<span class="hljs-variable">$0</span>(SleepTest02.java:13)<br>at java.base/java.lang.Thread.run(Thread.java:831)<br></code></pre></td></tr></table></figure><h1 id="3-yield方法"><a href="#3-yield方法" class="headerlink" title="3 yield方法"></a>3 yield方法</h1><p>当一个线程调用yield方法时,当前线程会让出CPU使用权,然后处于就绪状态,线程调度器会从就绪队列中选取一个优先级最高的线程执行,也有可能调度到刚刚让出CPU的那个线程来获取CPU执行权。该方法一般很少用。</p><blockquote><p><code>sleep</code>与<code>yield</code>比较:sleep与yield的区别是,当线程调用sleep是,该线程会进入阻塞状态,在睡眠期间CPU不会对该线程进行调用。而线程调用yield方法时,线程只是让出自己的CPU时间片,并未被阻塞,处于就绪状态,调度器在下一轮的调度时就有可能调到当前线程执行。</p></blockquote><h1 id="4-join方法"><a href="#4-join方法" class="headerlink" title="4 join方法"></a>4 join方法</h1><p>等待调用join方法的线程结束,再去执行后续任务。在项目实践中会遇到需要某几件事情完成后才继续往下执行,比如多个线程加载资源,需要等待多个线程加载完成后汇总处理。</p><p>下面的代码演示了其使用方法:</p><figure class="highlight livescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><code class="hljs livescript">public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">JoinTest</span> {</span><br> public <span class="hljs-keyword">static</span> <span class="hljs-literal">void</span> main(<span class="hljs-built_in">String</span>[] args) throws InterruptedException {<br> Thread threadA = <span class="hljs-keyword">new</span> Thread<span class="hljs-function"><span class="hljs-params">(() -> {</span></span><br><span class="hljs-params"><span class="hljs-function"> <span class="hljs-keyword">try</span> {</span></span><br><span class="hljs-params"><span class="hljs-function"> Thread.sleep(<span class="hljs-number">2500</span>);</span></span><br><span class="hljs-params"><span class="hljs-function"> } <span class="hljs-keyword">catch</span> (InterruptedException e) {</span></span><br><span class="hljs-params"><span class="hljs-function"> e.printStackTrace();</span></span><br><span class="hljs-params"><span class="hljs-function"> }</span></span><br><span class="hljs-params"><span class="hljs-function"> System.out.println(<span class="hljs-string">"Thread A done!"</span>);</span></span><br><span class="hljs-params"><span class="hljs-function"> })</span>;</span><br><span class="hljs-function"></span><br><span class="hljs-function"> <span class="hljs-title">Thread</span> <span class="hljs-title">threadB</span> = <span class="hljs-title">new</span> <span class="hljs-title">Thread</span><span class="hljs-params">(() -> {</span></span><br><span class="hljs-params"><span class="hljs-function"> <span class="hljs-keyword">try</span> {</span></span><br><span class="hljs-params"><span class="hljs-function"> Thread.sleep(<span class="hljs-number">1000</span>);</span></span><br><span class="hljs-params"><span class="hljs-function"> } <span class="hljs-keyword">catch</span> (InterruptedException e) {</span></span><br><span class="hljs-params"><span class="hljs-function"> e.printStackTrace();</span></span><br><span class="hljs-params"><span class="hljs-function"> }</span></span><br><span class="hljs-params"><span class="hljs-function"> System.out.println(<span class="hljs-string">"Thread B done!"</span>);</span></span><br><span class="hljs-params"><span class="hljs-function"> })</span>;</span><br><span class="hljs-function"></span><br><span class="hljs-function"> <span class="hljs-title">threadA</span>.<span class="hljs-title">start</span><span class="hljs-params">()</span>;</span><br><span class="hljs-function"> <span class="hljs-title">threadB</span>.<span class="hljs-title">start</span><span class="hljs-params">()</span>;</span><br><span class="hljs-function"> <span class="hljs-title">System</span>.<span class="hljs-title">out</span>.<span class="hljs-title">println</span><span class="hljs-params">(<span class="hljs-string">"Wait for all sub thread done!"</span>)</span>;</span><br><span class="hljs-function"> <span class="hljs-title">threadA</span>.<span class="hljs-title">join</span><span class="hljs-params">()</span>;</span><br><span class="hljs-function"> <span class="hljs-title">threadB</span>.<span class="hljs-title">join</span><span class="hljs-params">()</span>;</span><br><span class="hljs-function"> <span class="hljs-title">System</span>.<span class="hljs-title">out</span>.<span class="hljs-title">println</span><span class="hljs-params">(<span class="hljs-string">"continuing"</span>)</span>;</span><br><span class="hljs-function"> }</span><br><span class="hljs-function">}</span><br></code></pre></td></tr></table></figure><p>其运行结果如下:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs bash">Wait <span class="hljs-keyword">for</span> all sub thread <span class="hljs-keyword">done</span>!<br>Thread B <span class="hljs-keyword">done</span>!<br>Thread A <span class="hljs-keyword">done</span>!<br>continuing<br></code></pre></td></tr></table></figure><p>在主线程中调子线程调用<code>join</code>方法后,则主线程将会进入阻塞状态,直到子线程运行结束。上述代码中,主线程<code>threadA.join()</code>后进入阻塞状态,当结束后,由于此时线程B已经执行完成则无需阻塞,进入后续的步骤。线程A开始到两个线程结束,大约耗时2500毫秒。</p><h1 id="5-线程中断方法"><a href="#5-线程中断方法" class="headerlink" title="5 线程中断方法"></a>5 线程中断方法</h1><p>Java中的线程中断时一种线程间的协作模式,通过设置线程的中断标志并不能直接将线程杀死,而是由被中断线程根据中断状态自行处理。</p><ul><li><p><code>void interrupt()</code>方法:中断线程。当线程A运行时,线程B可以调用线程A的<code>interrupt</code>方法设置其中断标志并立即返回,再次强调:<strong>只是设置标志</strong>。如果线程A调用了<code>wait</code>函数、join方法或sleep方法,这时线程B再调用线程A的<code>interrupt</code>方法,则会抛出<code>InterruptedException</code>异常。</p></li><li><p><code>boolean isInterrupted()</code>方法:判断是当前线程是否设置了中断标志。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">isInterrupted</span><span class="hljs-params">()</span> </span>{<br> <span class="hljs-keyword">return</span> interrupted;<br> }<br></code></pre></td></tr></table></figure></li><li><p><code>boolean interrupted()</code>方法:检测当前线程是否设置了中断标志,与<code>isInterrupted()</code>方法不同的是,其会将中断标志设置为<code>false</code>,并通过本地方法<code>clearInterruptEvent</code>清除中断事件。</p><figure class="highlight angelscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs angelscript"><span class="hljs-keyword">public</span> static <span class="hljs-built_in">bool</span>ean <span class="hljs-built_in">int</span>errupted() {<br> Thread t = currentThread();<br> <span class="hljs-built_in">bool</span>ean <span class="hljs-built_in">int</span>errupted = t.<span class="hljs-built_in">int</span>errupted;<br> <span class="hljs-keyword">if</span> (<span class="hljs-built_in">int</span>errupted) {<br> t.<span class="hljs-built_in">int</span>errupted = <span class="hljs-literal">false</span>;<br> clearInterruptEvent();<br> }<br> <span class="hljs-keyword">return</span> <span class="hljs-built_in">int</span>errupted;<br> }<br></code></pre></td></tr></table></figure></li></ul>]]></content>
<tags>
<tag>Java</tag>
<tag>多线程</tag>
</tags>
</entry>
<entry>
<title>Java线程创建方式</title>
<link href="/2021/07/11/Java%E7%BA%BF%E7%A8%8B%E5%88%9B%E5%BB%BA%E6%96%B9%E5%BC%8F/"/>
<url>/2021/07/11/Java%E7%BA%BF%E7%A8%8B%E5%88%9B%E5%BB%BA%E6%96%B9%E5%BC%8F/</url>
<content type="html"><![CDATA[<p>一般来说我们比较常用的有以下三种方式,下面介绍它们的使用方法。</p><h1 id="1-继承Thread类"><a href="#1-继承Thread类" class="headerlink" title="1 继承Thread类"></a>1 继承Thread类</h1><p>通过继承 Thread 类,并重写它的 run 方法,就可以创建一个线程。 </p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ExtendThread</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Thread</span> </span>{<br><br> <span class="hljs-meta">@Override</span><br> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">run</span><span class="hljs-params">()</span> </span>{<br> System.out.println(Thread.currentThread().getName() + <span class="hljs-string">"is running..."</span>);<br> }<br><br> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{<br> <span class="hljs-comment">// 创建线程</span><br> ExtendThread thread = <span class="hljs-keyword">new</span> ExtendThread();<br> <span class="hljs-comment">// 设置线程名称</span><br> thread.setName(<span class="hljs-string">"my-thread"</span>);<br> <span class="hljs-comment">// 运行线程</span><br> thread.start();<br> }<br>}<br></code></pre></td></tr></table></figure><p>使用继承方式的好处是,在<code>run()</code>方法内获取当前线程直接使用this就可以了,无须使用<code>Thread.currentThread()</code>方法;不好的地方是Java不支持多继承,如果继承了<code>Thread</code>类,那么就不能再继承其他类。另外任务与代码没有分离,当多个线程执行一样的任务时需要多份任务代码</p><h1 id="2-实现-Runnable-接口"><a href="#2-实现-Runnable-接口" class="headerlink" title="2 实现 Runnable 接口"></a>2 实现 Runnable 接口</h1><p>实现<code>Runnable</code>类,并实现其<code>run()</code>方法,也可以创建一个线程。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ImplRunnable</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Runnable</span> </span>{<br> <span class="hljs-meta">@Override</span><br> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">run</span><span class="hljs-params">()</span> </span>{<br> System.out.println(Thread.currentThread().getName() + <span class="hljs-string">"is running..."</span>);<br> }<br><br> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{<br> ImplRunnable thread = <span class="hljs-keyword">new</span> ImplRunnable();<br> <span class="hljs-keyword">new</span> Thread(thread, <span class="hljs-string">"my-thread"</span>).start();<br> }<br>}<br></code></pre></td></tr></table></figure><p><code>Runnable</code>接口是一个被<code>@FunctionalInterface</code>注解修饰,因此可以通过lambda表达式进行创建,因此使用<code>Runnable</code>方式创建线程也可以通过下列方式进行简化:</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ImplRunnableLambda</span> </span>{<br> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{<br> <span class="hljs-keyword">new</span> Thread(() -> {<br> System.out.println(Thread.currentThread().getName() + <span class="hljs-string">"is running..."</span>);<br> }, <span class="hljs-string">"my-thread"</span>).start();<br> }<br></code></pre></td></tr></table></figure><h1 id="3-实现-Callable-接口,并结合-Future-实现"><a href="#3-实现-Callable-接口,并结合-Future-实现" class="headerlink" title="3 实现 Callable 接口,并结合 Future 实现"></a>3 实现 Callable 接口,并结合 Future 实现</h1><p>首先,要定义一个<code>Callable</code>实现类,并实现<code>call</code>方法;其次,通过<code>Future</code>的构造方法传入<code>Callable</code>实现类的实例;然后,把<code>FutureTask</code>作为<code>Thread</code>类的 target ,创建 <code>Thread </code>线程对象;最后,可以通过<code>Future</code>的<code>get</code>方法获取线程的运行结果。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UseFuture</span> </span>{<br> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> <span class="hljs-keyword">throws</span> ExecutionException, InterruptedException </span>{<br> FutureTask<String> futureTask = <span class="hljs-keyword">new</span> FutureTask<>(<span class="hljs-keyword">new</span> ImplCallable());<br> Thread thread = <span class="hljs-keyword">new</span> Thread(futureTask);<br> thread.start();<br> System.out.println(futureTask.get()); <span class="hljs-comment">// 获得线程运行后的返回值,阻塞式</span><br> }<br>}<br><br><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ImplCallable</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Callable</span><<span class="hljs-title">String</span>> </span>{<br> <span class="hljs-meta">@Override</span><br> <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">call</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> Exception </span>{<br> <span class="hljs-keyword">return</span> <span class="hljs-string">"thread execute finished"</span>;<br> }<br>}<br></code></pre></td></tr></table></figure><h1 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h1><ul><li><p>相比于第一种方式,更推荐第二种方式。因为继承继承<code>Thread</code>类往往不符合里氏代换原则,而实现<code>Runnable</code>接口可以使编程更加灵活,对外暴露的细节较少,使用者只需要关注<code>run()</code>方法的实现上;</p></li><li><p><code>Runnable</code>和<code>Callable</code>接口的定义如下:</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// Runnable接口</span><br><span class="hljs-meta">@FunctionalInterface</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Runnable</span> </span>{<br> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title">run</span><span class="hljs-params">()</span></span>;<br>}<br><br><span class="hljs-comment">// Callable接口</span><br><span class="hljs-meta">@FunctionalInterface</span><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Callable</span><<span class="hljs-title">V</span>> </span>{<br> <span class="hljs-function">V <span class="hljs-title">call</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> Exception</span>;<br>}<br></code></pre></td></tr></table></figure><p>通过对比两个接口定义可知<code>Runnable</code>和<code>Callable</code>有两点不同:(1)通过<code>call</code>方法可以获取返回值。前两种方式在任务结束后,无法直接获取执行结果,只能通过共享变量获取,而第三种则可解决这一问题;(2)<code>call</code>可以抛出要异常,<code>Runnable</code>则需要通过<code>setDefaultUncaughtExceptionHandler()</code>方法才能在主线程中获取子线程中的异常。</p></li></ul><p>每创建一个线程,实际上会在虚拟机栈上创建一个新的栈。因为每个虚拟机栈都是线程私有的,因此各线程之间不会相互干扰。</p>]]></content>
<tags>
<tag>Java</tag>
<tag>多线程</tag>
</tags>
</entry>
</search>