java多线程并发及线程池
来源:互联网 发布:程序员到架构师 编辑:程序博客网 时间:2024/05/25 18:12
<div id="article_details" class="details"> <div class="article_title"> <span class="ico ico_type_Original"></span> <h1> <span class="link_title"><a href="/u012385190/article/details/53302239"> java多线程并发及线程池 </a> </span> </h1></div> <div class="article_manage clearfix"> <div class="article_l"> <span class="link_categories"> 标签: <a href="http://www.csdn.net/tag/%e5%a4%9a%e7%ba%bf%e7%a8%8b" target="_blank" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_tag']);">多线程</a><a href="http://www.csdn.net/tag/java" target="_blank" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_tag']);">java</a> </span> </div> <div class="article_r"> <span class="link_postdate">2016-11-23 17:04</span> <span class="link_view" title="阅读次数">1537人阅读</span> <span class="link_comments" title="评论次数"> <a href="#comments" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_pinglun'])">评论</a>(0)</span> <span class="link_collect tracking-ad" data-mod="popu_171"> <a href="javascript:void(0);" onclick="javascript:collectArticle('java%e5%a4%9a%e7%ba%bf%e7%a8%8b%e5%b9%b6%e5%8f%91%e5%8f%8a%e7%ba%bf%e7%a8%8b%e6%b1%a0','53302239');return false;" title="收藏" target="_blank">收藏</a></span> <span class="link_report"> <a href="#report" onclick="javascript:report(53302239,2);return false;" title="举报">举报</a></span> </div> </div> <style type="text/css"> .embody{ padding:10px 10px 10px; margin:0 -20px; border-bottom:solid 1px #ededed; } .embody_b{ margin:0 ; padding:10px 0; } .embody .embody_t,.embody .embody_c{ display: inline-block; margin-right:10px; } .embody_t{ font-size: 12px; color:#999; } .embody_c{ font-size: 12px; } .embody_c img,.embody_c em{ display: inline-block; vertical-align: middle; } .embody_c img{ width:30px; height:30px; } .embody_c em{ margin: 0 20px 0 10px; color:#333; font-style: normal; } </style> <script type="text/javascript"> $(function () { try { var lib = eval("("+$("#lib").attr("value")+")"); var html = ""; if (lib.err == 0) { $.each(lib.data, function (i) { var obj = lib.data[i]; //html += '<img src="' + obj.logo + '"/>' + obj.name + " "; html += ' <a href="' + obj.url + '" target="_blank">'; html += ' <img src="' + obj.logo + '">'; html += ' <em><b>' + obj.name + '</b></em>'; html += ' </a>'; }); if (html != "") { setTimeout(function () { $("#lib").html(html); $("#embody").show(); }, 100); } } } catch (err) { } }); </script> <div class="category clearfix"> <div class="category_l"> <img src="http://static.blog.csdn.net/images/category_icon.jpg"> <span>分类:</span> </div> <div class="category_r"> <label onclick="GetCategoryArticles('6536400','u012385190','top','53302239');"> <span onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_fenlei']);">线程<em>(1)</em></span> <img class="arrow-down" src="http://static.blog.csdn.net/images/arrow_triangle _down.jpg" style="display:inline;"> <img class="arrow-up" src="http://static.blog.csdn.net/images/arrow_triangle_up.jpg" style="display:none;"> <div class="subItem"> <div class="subItem_t"><a href="http://blog.csdn.net/u012385190/article/category/6536400" target="_blank">作者同类文章</a><i class="J_close">X</i></div> <ul class="subItem_l" id="top_6536400"> </ul> </div> </label> </div> </div> <div class="bog_copyright"> <p class="copyright_p">版权声明:本文为博主原创文章,转载请指明文章出处!</p> </div> <div style="clear:both"></div><div style="border:solid 1px #ccc; background:#eee; float:left; min-width:200px;padding:4px 10px;"><p style="text-align:right;margin:0;"><span style="float:left;">目录<a href="#" title="系统根据文章中H1到H6标签自动生成文章目录">(?)</a></span><a href="#" onclick="javascript:return openct(this);" title="展开">[+]</a></p><ol style="display:none;margin-left:14px;padding-left:14px;line-height:160%;"><li><a href="#t0">线程的常用创建方式</a></li><li><a href="#t1">多线程并发</a></li><li><a href="#t2">线程池</a></li></ol></div><div style="clear:both"></div><div id="article_content" class="article_content tracking-ad" data-mod="popu_307" data-dsm="post"> <div class="markdown_views"><h2 id="线程的常用创建方式"><a name="t0" target="_blank"></a>线程的常用创建方式</h2><p>1、继承Thread类创建线程类</p><pre class="prettyprint" name="code"><code class="hljs java has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FirstThreadTest</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Thread</span> {</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">run</span>(){ System.out.println(<span class="hljs-string">"这里是线程的执行方法"</span>); } <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span>(String[] args) { <span class="hljs-comment">//获得线程</span> FirstThreadTest thread = <span class="hljs-keyword">new</span> FirstThreadTest(); System.out.println(<span class="hljs-string">"线程名称为:"</span>+thread.getName()); <span class="hljs-comment">//启动线程</span> thread.start(); System.out.println(<span class="hljs-string">"main方法也是一个线程:"</span>+Thread.currentThread().getName()); }}</code><ul class="pre-numbering" style="opacity: 0;"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li></ul><div class="save_code tracking-ad" data-mod="popu_249" style="display: none;"><a href="javascript:;" target="_blank"><img src="http://static.blog.csdn.net/images/save_snippets.png"></a></div><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li></ul></pre><p>执行结果:</p><pre class="prettyprint" name="code"><code class="hljs mathematica has-numbering">线程名称为:<span class="hljs-keyword">Thread</span>-<span class="hljs-number">0</span>main方法也是一个线程:main这里是线程的执行方法</code><ul class="pre-numbering" style="opacity: 0;"><li>1</li><li>2</li><li>3</li></ul><div class="save_code tracking-ad" data-mod="popu_249"><a href="javascript:;" target="_blank"><img src="http://static.blog.csdn.net/images/save_snippets.png"></a></div><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li></ul></pre><p>2、通过Runnable接口创建线程类 <br>(1)定义runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体; <br>(2)创建 Runnable实现类的实例,并依此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象; <br>(3)调用线程对象的start()方法来启动该线程。</p><pre class="prettyprint" name="code"><code class="hljs java has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RunnableThreadTest</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Runnable</span> {</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">run</span>() { System.out.println(<span class="hljs-string">"这里是线程方法"</span>); System.out.println(<span class="hljs-string">"线程名为:"</span> + Thread.currentThread().getName()); } <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span>(String[] args) { System.out.println(<span class="hljs-string">"main方法线程:"</span> + Thread.currentThread().getName()); RunnableThreadTest rtt = <span class="hljs-keyword">new</span> RunnableThreadTest(); <span class="hljs-keyword">new</span> Thread(rtt, <span class="hljs-string">"新线程1"</span>).start(); <span class="hljs-keyword">new</span> Thread(rtt, <span class="hljs-string">"新线程2"</span>).start(); }}</code><ul class="pre-numbering" style="opacity: 0;"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li></ul><div class="save_code tracking-ad" data-mod="popu_249"><a href="javascript:;" target="_blank"><img src="http://static.blog.csdn.net/images/save_snippets.png"></a></div><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li></ul></pre><p>执行结果</p><pre class="prettyprint" name="code"><code class="hljs has-numbering">main方法线程:main这里是线程方法线程名为:新线程1这里是线程方法线程名为:新线程2</code><ul class="pre-numbering" style="opacity: 0;"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li></ul><div class="save_code tracking-ad" data-mod="popu_249"><a href="javascript:;" target="_blank"><img src="http://static.blog.csdn.net/images/save_snippets.png"></a></div><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li></ul></pre><p>两种线程创建的具体区别:<a href="http://www.cnblogs.com/whgw/archive/2011/10/03/2198506.html" target="_blank">http://www.cnblogs.com/whgw/archive/2011/10/03/2198506.html</a>(扩展性和资源共享性)</p><h2 id="多线程并发"><a name="t1" target="_blank"></a>多线程并发</h2><p>多线程并发出现问题主要涉及到两个方面:多线程共享数据同步问题和数据因并发产生不一致问题;</p><p>1、多线程共享数据同步问题 <br>如下代码:</p><pre class="prettyprint" name="code"><code class="hljs java has-numbering"><span class="hljs-javadoc">/** * 两个工人一起搬砖 */</span><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Banzhuan</span> {</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span>(String[] args) { <span class="hljs-comment">// 一个工厂</span> Factory factory = <span class="hljs-keyword">new</span> Factory(); <span class="hljs-javadoc">/** * p1线程和p2线程都是由factory这个实例创建的 * 那么p1调用外部类的getZhuanTou()方法就相当于调用的是factory这个实例的getZhuanTou(),同样的,p2调用的也是factory这个实例的getZhuanTou(). * 那么这里就出现了两个线程同时访问factory的getZhuanTou()方法。 * 而factory的getZhuanTou()方法又对zhuanTou这个属性进行了zhuanTou--操作。 * 换句话说,两个线程同时访问了factory的数据zhuanTou.这时候就可能产生线程安全问题。 */</span> <span class="hljs-comment">// 同一个工厂的两个工人</span> Person p1 = factory.getPerson(); Person p2 = factory.getPerson(); p1.start(); p2.start(); }}<span class="hljs-comment">// 工厂</span>class Factory { <span class="hljs-keyword">int</span> zhuanTou = <span class="hljs-number">20</span>;<span class="hljs-comment">// 一共20块砖头</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getZhuanTou</span>() { <span class="hljs-keyword">if</span> (zhuanTou == <span class="hljs-number">0</span>) { <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> RuntimeException(Thread.currentThread().getName()+ <span class="hljs-string">",没有砖头搬了!"</span>); } Thread.yield(); <span class="hljs-keyword">return</span> zhuanTou--; } <span class="hljs-comment">// 工人</span> class Person extends Thread { <span class="hljs-comment">// 不停的搬砖</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">run</span>() { <span class="hljs-keyword">while</span> (<span class="hljs-keyword">true</span>) { <span class="hljs-comment">// 获取线程名(工人名) 及 剩下砖头数</span> System.out.println(getName() + <span class="hljs-string">"搬了第"</span> + getZhuanTou() + <span class="hljs-string">"块砖头"</span>); <span class="hljs-comment">// 当线程的run方法中出现了异常,且我们没有 解决,那么该线程终止并死亡。但不会影响 当前进程中的其他线程。</span> Thread.yield(); } } } <span class="hljs-comment">// 获取工人</span> <span class="hljs-keyword">public</span> Person <span class="hljs-title">getPerson</span>() { <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Person(); }}</code><ul class="pre-numbering" style="opacity: 0;"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li><li>36</li><li>37</li><li>38</li><li>39</li><li>40</li><li>41</li><li>42</li><li>43</li><li>44</li><li>45</li><li>46</li><li>47</li><li>48</li><li>49</li><li>50</li><li>51</li><li>52</li><li>53</li></ul><div class="save_code tracking-ad" data-mod="popu_249"><a href="javascript:;" target="_blank"><img src="http://static.blog.csdn.net/images/save_snippets.png"></a></div><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li><li>36</li><li>37</li><li>38</li><li>39</li><li>40</li><li>41</li><li>42</li><li>43</li><li>44</li><li>45</li><li>46</li><li>47</li><li>48</li><li>49</li><li>50</li><li>51</li><li>52</li><li>53</li></ul></pre><p><strong>多次</strong>运行结果: <br><img src="http://img.blog.csdn.net/20161123140324842" alt="这里写图片描述" title=""></p><p><strong>这里并不是每次都会出错,要多运行几次,就会可能碰到多种错误</strong>,比如搬到了同一块砖,比如少搬一块砖,比如搬完到了0然后还有继续搬…… <br>原因是:比如现在还剩15块砖头,工人p1搬第15块砖头的时候正拿到手上,但是还没有登记减少一块砖头(即还没有运行zhuanTou–),这个时候工人p2也去拿砖,然后登记的时候一看还剩15块砖头,实际呢只剩14块了…… <br><strong>解决方法:</strong> <br>synchronized:当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。 <br>所以将getZhuanTou()方法改成如下就可以了</p><pre class="prettyprint" name="code"><code class="hljs cs has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getZhuanTou</span>() { synchronized (<span class="hljs-keyword">this</span>) { <span class="hljs-keyword">if</span> (zhuanTou == <span class="hljs-number">0</span>) { <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> RuntimeException(Thread.currentThread().getName()+<span class="hljs-string">",没有砖头搬了!"</span>); } Thread.<span class="hljs-keyword">yield</span>(); <span class="hljs-keyword">return</span> zhuanTou--; } }</code><ul class="pre-numbering" style="opacity: 0;"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li></ul><div class="save_code tracking-ad" data-mod="popu_249"><a href="javascript:;" target="_blank"><img src="http://static.blog.csdn.net/images/save_snippets.png"></a></div><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li></ul></pre><p>为啥不将这个关键词锁在方法那呢?尽量将锁在范围最小的地方,这样运行的效率更快。</p><p>2、数据因并发产生不一致问题 <br>参考:<a href="https://my.oschina.net/clopopo/blog/149368" target="_blank">https://my.oschina.net/clopopo/blog/149368</a></p><p><strong>ThreadLocal</strong>:为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象。</p><p>首先,ThreadLocal 不是用来解决共享对象的多线程访问问题的,一般情况下,通过ThreadLocal.set() 到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问不到的。各个线程中访问的是不同的对象; </p><p>另外,说ThreadLocal使得各线程能够保持各自独立的一个对象,并不是通过ThreadLocal.set()来实现的,而是通过每个线程中的new 对象的操作来创建的对象,每个线程创建一个,不是什么对象的拷贝或副本。</p><p>再次,注意每一个线程都保存一个对象的时候(非基本类型数据)应该是new一个新对象而不是引用一个对象,如下:</p><pre class="prettyprint" name="code"><code class="hljs java has-numbering"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> ThreadLocal<Index> local = <span class="hljs-keyword">new</span> ThreadLocal<Index>() { <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">protected</span> Index <span class="hljs-title">initialValue</span>() { <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Index(); <span class="hljs-comment">//注意这里</span> } };</code><ul class="pre-numbering" style="opacity: 0;"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li></ul><div class="save_code tracking-ad" data-mod="popu_249"><a href="javascript:;" target="_blank"><img src="http://static.blog.csdn.net/images/save_snippets.png"></a></div><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li></ul></pre><p>案例代码:</p><pre class="prettyprint" name="code"><code class="hljs cs has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> ThreadLocalTest { <span class="hljs-comment">//创建一个Integer型的线程本地变量</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> final ThreadLocal<Integer> local = <span class="hljs-keyword">new</span> ThreadLocal<Integer>() { @Override <span class="hljs-keyword">protected</span> Integer <span class="hljs-title">initialValue</span>() { <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>; } }; <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span>(String[] args) throws InterruptedException { Thread[] threads = <span class="hljs-keyword">new</span> Thread[<span class="hljs-number">5</span>]; <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> j = <span class="hljs-number">0</span>; j < <span class="hljs-number">5</span>; j++) { threads[j] = <span class="hljs-keyword">new</span> Thread(<span class="hljs-keyword">new</span> Runnable() { @Override <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">run</span>() { <span class="hljs-comment">//获取当前线程的本地变量,然后累加5次</span> <span class="hljs-keyword">int</span> num = local.<span class="hljs-keyword">get</span>(); <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < <span class="hljs-number">5</span>; i++) { num++; } <span class="hljs-comment">//重新设置累加后的本地变量</span> local.<span class="hljs-keyword">set</span>(num); System.<span class="hljs-keyword">out</span>.println(Thread.currentThread().getName() + <span class="hljs-string">" : "</span>+ local.<span class="hljs-keyword">get</span>()); } }, <span class="hljs-string">"Thread-"</span> + j); } <span class="hljs-keyword">for</span> (Thread thread : threads) { thread.start(); } }}</code><ul class="pre-numbering" style="opacity: 0;"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li></ul><div class="save_code tracking-ad" data-mod="popu_249"><a href="javascript:;" target="_blank"><img src="http://static.blog.csdn.net/images/save_snippets.png"></a></div><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li></ul></pre><p>运行结果: <br>Thread-0 : 5 <br>Thread-4 : 5 <br>Thread-2 : 5 <br>Thread-1 : 5 <br>Thread-3 : 5</p><pre class="prettyprint" name="code"><code class="hljs brainfuck has-numbering"><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span></code><ul class="pre-numbering" style="opacity: 0;"><li>1</li></ul><div class="save_code tracking-ad" data-mod="popu_249"><a href="javascript:;" target="_blank"><img src="http://static.blog.csdn.net/images/save_snippets.png"></a></div><ul class="pre-numbering"><li>1</li></ul></pre><p>3、总结: <br>ThreadLocal和Synchonized都用于解决多线程并发访问。但是ThreadLocal与synchronized有本质的区别: <br>1、synchronized关键字主要解决多线程共享数据同步问题,ThreadLocal使用场合主要解决多线程中数据因并发产生不一致问题; <br>2、synchronized是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问。而ThreadLocal为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。而Synchronized却正好相反,它用于在多个线程间通信时能够获得数据共享; <br>synchronized和ThreadLocal比较:<a href="http://blog.csdn.net/huyongl1989/article/details/8088841" target="_blank">http://blog.csdn.net/huyongl1989/article/details/8088841</a></p><h2 id="线程池"><a name="t2" target="_blank"></a>线程池</h2><p>当有许多请求需要去处理的时候,如果只是单独的一个人去处理,可想而知那会让后面在排队的人等多久,这样就需要线程池,有请求过来了就到线程池里面取出一条线程去处理它,处理完成就把它收回到线程池里面,然而自己实现 一个功能强大的线程池也并非易事,在java1.5之后专门提供了线程池的类库。</p><p><a href="http://lib.csdn.net/base/java" class="replace_word" title="Java 知识库" target="_blank" style="color:#df3434; font-weight:bold;">Java</a>通过Executors接口提供四种线程池,分别为: <br>newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程; <br>newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待; <br>newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行; <br>newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行; <br>下面简单看一下newFixedThreadPool这种线程池:</p><pre class="prettyprint" name="code"><code class="hljs cs has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> ThreadPoolExecutorTest { <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span>(String[] args) { ExecutorService fixedThreadPool = Executors.newFixedThreadPool(<span class="hljs-number">3</span>); <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < <span class="hljs-number">10</span>; i++) { final <span class="hljs-keyword">int</span> index = i; fixedThreadPool.submit(<span class="hljs-keyword">new</span> Runnable() { <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">run</span>() { <span class="hljs-keyword">try</span> { System.<span class="hljs-keyword">out</span>.println(Thread.currentThread().getName()+<span class="hljs-string">"---->"</span>+index); Thread.sleep(<span class="hljs-number">2000</span>); } <span class="hljs-keyword">catch</span> (InterruptedException e) { e.printStackTrace(); } } }); } }}</code><ul class="pre-numbering" style="opacity: 0;"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li></ul><div class="save_code tracking-ad" data-mod="popu_249"><a href="javascript:;" target="_blank"><img src="http://static.blog.csdn.net/images/save_snippets.png"></a></div><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li></ul></pre><p>运行: <br>pool-1-thread-1—->0 <br>pool-1-thread-3—->2 <br>pool-1-thread-2—->1 <br>pool-1-thread-3—->3 <br>pool-1-thread-2—->5 <br>pool-1-thread-1—->4 <br>pool-1-thread-3—->6 <br>pool-1-thread-1—->8 <br>pool-1-thread-2—->7 <br>pool-1-thread-3—->9</p><p>因为线程池大小为3,每个任务输出index后sleep 2秒,所以每两秒打印3个数字。 <br>fixedThreadPool.submit(Runnable task)或者execute方法会调用线程的run方法;</p><p>线程池参考地址:<a href="http://blog.csdn.net/u012385190/article/details/52486393" target="_blank">http://blog.csdn.net/u012385190/article/details/52486393</a></p></div> <script type="text/javascript"> $(function () { $('pre.prettyprint code').each(function () { var lines = $(this).text().split('\n').length; var $numbering = $('<ul></ul>').addClass('pre-numbering').hide(); $(this).addClass('has-numbering').parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($('<li></li>').text(i)); }; $numbering.fadeIn(1700); }); }); </script> </div><!-- Baidu Button BEGIN --><div class="bdsharebuttonbox tracking-ad bdshare-button-style0-16" style="float: right;" data-mod="popu_172" data-bd-bind="1498814705862"><a href="#" class="bds_more" data-cmd="more" style="background-position:0 0 !important; background-image: url(http://bdimg.share.baidu.com/static/api/img/share/icons_0_16.png?v=d754dcc0.png) !important" target="_blank"></a><a href="#" class="bds_qzone" data-cmd="qzone" title="分享到QQ空间" style="background-position:0 -52px !important" target="_blank"></a><a href="#" class="bds_tsina" data-cmd="tsina" title="分享到新浪微博" style="background-position:0 -104px !important" target="_blank"></a><a href="#" class="bds_tqq" data-cmd="tqq" title="分享到腾讯微博" style="background-position:0 -260px !important" target="_blank"></a><a href="#" class="bds_renren" data-cmd="renren" title="分享到人人网" style="background-position:0 -208px !important" target="_blank"></a><a href="#" class="bds_weixin" data-cmd="weixin" title="分享到微信" style="background-position:0 -1612px !important" target="_blank"></a></div><script>window._bd_share_config = { "common": { "bdSnsKey": {}, "bdText": "", "bdMini": "1", "bdMiniList": false, "bdPic": "", "bdStyle": "0", "bdSize": "16" }, "share": {} }; with (document) 0[(getElementsByTagName('head')[0] || body).appendChild(createElement('script')).src = 'http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion=' + ~(-new Date() / 36e5)];</script><!-- Baidu Button END --> <!--172.16.140.13--><!-- Baidu Button BEGIN --><script type="text/javascript" id="bdshare_js" data="type=tools&uid=1536434" src="http://bdimg.share.baidu.com/static/js/bds_s_v2.js?cdnversion=416338"></script><script type="text/javascript"> document.getElementById("bdshell_js").src = "http://bdimg.share.baidu.com/static/js/shell_v2.js?cdnversion=" + Math.ceil(new Date()/3600000)</script><!-- Baidu Button END --> <div id="digg" articleid="53302239"> <dl id="btnDigg" class="digg digg_enable" onclick="btndigga();"> <dt>顶</dt> <dd>1</dd> </dl> <dl id="btnBury" class="digg digg_enable" onclick="btnburya();"> <dt>踩</dt> <dd>0</dd> </dl> </div> <div class="tracking-ad" data-mod="popu_222"><a href="javascript:void(0);" target="_blank"> </a> </div> <div class="tracking-ad" data-mod="popu_223"> <a href="javascript:void(0);" target="_blank"> </a></div> <script type="text/javascript"> function btndigga() { $(".tracking-ad[data-mod='popu_222'] a").click(); } function btnburya() { $(".tracking-ad[data-mod='popu_223'] a").click(); } </script> <ul class="article_next_prev"> <li class="prev_article"><span onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_shangyipian']);location.href='http://blog.csdn.net/u012385190/article/details/53198345';">上一篇</span><a href="http://blog.csdn.net/u012385190/article/details/53198345" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_shangyipian'])">mybatis相关介绍</a></li> <li class="next_article"><span onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_xiayipian']);location.href='http://blog.csdn.net/u012385190/article/details/53331432';">下一篇</span><a href="http://blog.csdn.net/u012385190/article/details/53331432" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_xiayipian'])">Spring quartz定时任务Service注入问题</a></li> </ul> <div style="clear:both; height:10px;"></div> <div class="similar_article"> <h4></h4> <div class="similar_c" style="margin:20px 0px 0px 0px"> <div class="similar_c_t"> 相关文章推荐 </div> <div class="similar_wrap tracking-ad" data-mod="popu_36"> <ul class="similar_list fl"> <li> <em>•</em> <a href="http://blog.csdn.net/cqkxboy168/article/details/9026205" title="并发 并行 同步 异步 多线程的区别" strategy="BlogCommendFromBaidu" target="_blank">并发 并行 同步 异步 多线程的区别</a> </li> <li> <em>•</em> <a href="http://blog.csdn.net/escaflone/article/details/10418651" title="Java 多线程 并发编程" strategy="BlogCommendFromBaidu" target="_blank">Java 多线程 并发编程</a> </li> <li> <em>•</em> <a href="http://blog.csdn.net/he90227/article/details/47252793" title="多线程与并发知识点总结" strategy="BlogCommendFromBaidu" target="_blank">多线程与并发知识点总结</a> </li> <li> <em>•</em> <a href="http://blog.csdn.net/luozhonghua2014/article/details/44170867" title="多线程并发快速处理数据" strategy="BlogCommendFromBaidu" target="_blank">多线程并发快速处理数据</a> </li> <li> <em>•</em> <a href="http://blog.csdn.net/qq_33290787/article/details/51790605" title="多线程 ---并发与并行概念总结" strategy="BlogCommendFromBaidu" target="_blank">多线程 ---并发与并行概念总结</a> </li> </ul> <ul class="similar_list fr"> <li> <em>•</em> <a href="http://blog.csdn.net/z69183787/article/details/52910299" title="线程与进程的区别以及对多线程并发的理解" strategy="BlogCommendFromBaidu" target="_blank">线程与进程的区别以及对多线程并发的理解</a> </li> <li> <em>•</em> <a href="http://blog.csdn.net/eson_15/article/details/51553597" title="【java并发】线程并发库的使用" strategy="BlogCommendFromBaidu" target="_blank">【java并发】线程并发库的使用</a> </li> <li> <em>•</em> <a href="http://blog.csdn.net/zhoudaxia/article/details/24294583" title="Java并发与多线程教程(1)" strategy="BlogCommendFromBaidu" target="_blank">Java并发与多线程教程(1)</a> </li> <li> <em>•</em> <a href="http://blog.csdn.net/cselmu9/article/details/51366946" title="高并发下线程安全的单例模式(最全最经典)" strategy="BlogCommendFromBaidu" target="_blank">高并发下线程安全的单例模式(最全最经典)</a> </li> <li> <em>•</em> <a href="http://ahua186186.iteye.com/blog/2109498" title="总结--线程池拒绝策略+线程中断处理+多线程并发任务处理" strategy="BlogCommendFromCsdn" target="_blank">总结--线程池拒绝策略+线程中断处理+多线程并发任务处理</a> </li> </ul> </div> </div> </div> </div>
阅读全文
0 0
- java多线程并发及线程池
- java多线程并发及线程池
- java 基础学习之线程--多线程并发及线程锁
- Java多线程/并发18、Java线程池
- 【多线程高并发】java线程池
- 多线程及线程并发库
- Java面试题--多线程、并发及线程的基础问题
- java多线程及并发
- Java多线程及线程池
- java多线程及线程池
- java并发——多线程、线程池、并发集合
- 多线程及线程周期和多线程并发
- 【java多线程与并发库】---传统java多线程<4> .线程状态及优先级
- Java多线程,线程同步synchronized,线程死锁【线程池常规用法】多线程并发处理
- 多线程及java5的线程并发库
- 多线程、并发及线程的基础问题
- java多线程并发库高级应用 之 java5中的线程并发库--线程池、Callable&Future
- 【Java多线程与并发库】8.java5线程并发库之线程池的应用
- MongoDB和Redis区别
- Android 官方兼容库 EmojiCompat Support Library
- Linux线程学习总结
- 自动布局之autoresizingMask使用详解(Storyboard&Code)
- finally和return执行前后顺序关系
- java多线程并发及线程池
- windows下编译hadoop成功 执行异常org.apache.hadoop.io.nativeio.NativeIO$Windows.access0(Ljava/lang/String;I)Z
- 设计模式之——观察者模式(触发联动)
- 关于Spring MVC上传文件的坑
- Lake Counting
- cmake 设置vs工程的MT、MTd
- mysql insert异常,springmvc 请求异常 404
- mybatis传多个参数(三种方法)详细
- Cardboard的学习(三)目录介绍