﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-java 友人帮-文章分类-多线程</title><link>http://www.blogjava.net/jzone/category/40827.html</link><description>java web, java wap ..My laboratory..</description><language>zh-cn</language><lastBuildDate>Tue, 12 Jan 2010 18:21:51 GMT</lastBuildDate><pubDate>Tue, 12 Jan 2010 18:21:51 GMT</pubDate><ttl>60</ttl><item><title>java多线程及其状态</title><link>http://www.blogjava.net/jzone/articles/308909.html</link><dc:creator>Gavin.lee</dc:creator><author>Gavin.lee</author><pubDate>Sun, 10 Jan 2010 05:38:00 GMT</pubDate><guid>http://www.blogjava.net/jzone/articles/308909.html</guid><description><![CDATA[<a href="http://hi.baidu.com/lieyu063/blog/item/0e816eb53f0c3ccc37d3cac7.html">http://hi.baidu.com/lieyu063/blog/item/0e816eb53f0c3ccc37d3cac7.html</a> <br />
<a href="http://lavasoft.blog.51cto.com/62575/27069">http://lavasoft.blog.51cto.com/62575/27069</a> 
<img src ="http://www.blogjava.net/jzone/aggbug/308909.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jzone/" target="_blank">Gavin.lee</a> 2010-01-10 13:38 <a href="http://www.blogjava.net/jzone/articles/308909.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用 Java Debug Interface（JDI）调试多线程应用程序</title><link>http://www.blogjava.net/jzone/articles/304446.html</link><dc:creator>Gavin.lee</dc:creator><author>Gavin.lee</author><pubDate>Tue, 01 Dec 2009 14:53:00 GMT</pubDate><guid>http://www.blogjava.net/jzone/articles/304446.html</guid><description><![CDATA[<a href="http://www.ibm.com/developerworks/cn/java/j-lo-jdi/">http://www.ibm.com/developerworks/cn/java/j-lo-jdi/</a> 
<img src ="http://www.blogjava.net/jzone/aggbug/304446.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jzone/" target="_blank">Gavin.lee</a> 2009-12-01 22:53 <a href="http://www.blogjava.net/jzone/articles/304446.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java.lang.Thread 的几个状态（有助与观察java dump，通过状态分析程序性能）</title><link>http://www.blogjava.net/jzone/articles/303980.html</link><dc:creator>Gavin.lee</dc:creator><author>Gavin.lee</author><pubDate>Fri, 27 Nov 2009 14:11:00 GMT</pubDate><guid>http://www.blogjava.net/jzone/articles/303980.html</guid><description><![CDATA[<strong><span style="color: green">1.NEW</span></strong> <br />
至今尚未启动的线程的状态。 <br />
<br />
<strong><span style="color: green">2.RUNNABLE</span></strong> <br />
可运行线程的线程状态。处于可运行状态的某一线程正在 Java 虚拟机中运行，但它可能正在等待操作系统中的其他资源，比如处理器。 <br />
<br />
<strong><span style="color: green">3.BLOCKED</span></strong> <br />
受阻塞并且正在等待监视器锁的某一线程的线程状态。处于受阻塞状态的某一线程正在等待监视器锁，以便进入一个同步的块/方法，或者在调用 Object.wait 之后再次进入同步的块/方法。 <br />
<br />
<strong><span style="color: green">4.WAITING</span></strong> <br />
某一等待线程的线程状态。某一线程因为调用下列方法之一而处于等待状态： <br />
<ul>
    <li>不带超时值的 Object.wait
    <li>不带超时值的 Thread.join </li>
</ul>
<br />
LockSupport.park <br />
处于等待状态的线程正等待另一个线程，以执行特定操作。 例如，已经在某一对象上调用了 Object.wait() 的线程正等待另一个线程，以便在该对象上调用 Object.notify() 或 Object.notifyAll()。已经调用了 Thread.join() 的线程正在等待指定线程终止。 <br />
<br />
<strong><span style="color: green">5.TIMED_WAITING</span></strong>具有指定等待时间的某一等待线程的线程状态。某一线程因为调用以下带有指定正等待时间的方法之一而处于定时等待状态： <br />
<ul>
    <li>Thread.sleep
    <li>带有超时值的 Object.wait
    <li>带有超时值的 Thread.join
    <li>LockSupport.parkNanos
    <li>LockSupport.parkUntil </li>
</ul>
<br />
<strong><span style="color: green">6.TERMINATED</span></strong> <br />
已终止线程的线程状态。线程已经结束执行。 <br />
<br />
<strong>注意：在给定时间点上，一个线程只能处于一种状态。这些状态是虚拟机状态，它们并没有反映所有操作系统线程状态。</strong> <br />
<br />
为了展现线程在运行时的状态及其转换，我画了下面这个图： <br />
<strong><span style="color: green"><img alt="" src="http://www.blogjava.net/images/blogjava_net/jzone/200911/thread-state.jpg" border="0" /></span></strong><br />
 <img src ="http://www.blogjava.net/jzone/aggbug/303980.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jzone/" target="_blank">Gavin.lee</a> 2009-11-27 22:11 <a href="http://www.blogjava.net/jzone/articles/303980.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>多线程实用操作方法大全</title><link>http://www.blogjava.net/jzone/articles/287381.html</link><dc:creator>Gavin.lee</dc:creator><author>Gavin.lee</author><pubDate>Sun, 19 Jul 2009 15:41:00 GMT</pubDate><guid>http://www.blogjava.net/jzone/articles/287381.html</guid><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;线程控制基本方法&nbsp; 方&nbsp;&nbsp;&nbsp;&nbsp;法&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&...&nbsp;&nbsp;<a href='http://www.blogjava.net/jzone/articles/287381.html'>阅读全文</a><img src ="http://www.blogjava.net/jzone/aggbug/287381.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jzone/" target="_blank">Gavin.lee</a> 2009-07-19 23:41 <a href="http://www.blogjava.net/jzone/articles/287381.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>线程理论基础</title><link>http://www.blogjava.net/jzone/articles/287371.html</link><dc:creator>Gavin.lee</dc:creator><author>Gavin.lee</author><pubDate>Sun, 19 Jul 2009 13:10:00 GMT</pubDate><guid>http://www.blogjava.net/jzone/articles/287371.html</guid><description><![CDATA[线程：是指进程中的一个执行流程。换言之：一个程序不同的执行路径<br />
进程：实际是静态文件，所以说进程是个静态概念，实际运行的都是线程。<br />
<br />
多线程：在同一个应用程序中有多个顺序流同时执行<br />
多进程：在操作系统中能同时运行多个任务（程序)<br />
<br />
线程与进程的区别：每个进程都需要操作系统为其分配独立的内存地址空间，而同一进程中的所有线程在同一块地址空间中工作，这些线程可以共享同一块内存和系统资源。<br />
<br />
请先理解下面这句话：一个进程是一个正运行的应用程序的实例 。它由两个部分组成：一个是操作系统用来管理这个进程的内核对象。另一个是这个进程拥有的地址空间。从执行角度方面看，一个进程由一个或多个线程组成。一个线程是一个执行单元，它控制CPU执行进程中某一段代码段。一个线程可以访问这个进程中所有的地址空间和资源。一个进程最少包括一个线程来执行代码，这个线程又叫做主线程。 　线程除了能够访问进程的资源外，每个线程还拥有自己的栈 <br />
<br />
<br />
创建线程有两种方式，如下： <br />
1、 扩展java.lang.Thread类，重载run<br />
2、 实现Runnable接口，重写run<br />
Thread类代表线程类，它的两个最主要的方法是： <br />
run()——包含线程运行时所执行的代码（线程体） <br />
start()——用于启动线程 <br />
<br />
<br />
一个线程只能被启动一次。第二次启动时将会抛出java.lang.IllegalThreadExcetpion异常 <br />
<br />
在同一个时间点，一个CPU只支持一个线程<br />
<br />
真正的多线程只存在与多CPU<br />
<br />
所以说但CPU操作系统只能说支持多线程<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
<br />
两种线程模式<br />
协作式:一个线程保留对处理器的控制直到它自己决定放弃&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a.速度快、代价低&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b.用户编程非常麻烦&nbsp;<br />
抢先式:系统可以任意的从线程中夺回对CPU的控制权，再把控制权分给其它的线程 。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a.两次切换之间的时间间隔就叫做时间片&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b.效率不如协作式高 ，OS核心必须负责管理线程&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c.简化编程，而且使程序更加可靠 <br />
多数线程的调度是抢先式的<br />
<br />
同一个线程类，可new出两个线程对象<br />
<br />
<br />
<br />
<br />
线程：是指进程中的一个执行流程。 <br />
线程与进程的区别：每个进程都需要操作系统为其分配独立的内存地址空间，而同一进程中的所有线程在同一块地址空间中工作，这些线程可以共享同一块内存和系统资源。 <br />
<br />
<br />
如何创建一个线程？ <br />
<br />
创建线程有两种方式，如下： <br />
1、 扩展java.lang.Thread类 <br />
2、 实现Runnable接口 <br />
Thread类代表线程类，它的两个最主要的方法是： <br />
run()——包含线程运行时所执行的代码 <br />
Start()——用于启动线程 <br />
<br />
一个线程只能被启动一次。第二次启动时将会抛出java.lang.IllegalThreadExcetpion异常 <br />
<br />
线程间状态的转换（如图示） <br />
<br />
新建状态：用new语句创建的线程对象处于新建状态，此时它和其它的java对象一样，仅仅在堆中被分配了内存 <br />
就绪状态：当一个线程创建了以后，其他的线程调用了它的start()方法，该线程就进入了就绪状态。处于这个状态的线程位于可运行池中，等待获得CPU的使用权 <br />
运行状态：处于这个状态的线程占用CPU,执行程序的代码 <br />
阻塞状态：当线程处于阻塞状态时，java虚拟机不会给线程分配CPU，直到线程重新进入就绪状态，它才有机会转到运行状态。 <br />
阻塞状态分为三种情况： <br />
1、 位于对象等待池中的阻塞状态：当线程运行时，如果执行了某个对象的wait()方法，java虚拟机就回把线程放到这个对象的等待池中 <br />
2、 位于对象锁中的阻塞状态，当线程处于运行状态时，试图获得某个对象的同步锁时，如果该对象的同步锁已经被其他的线程占用，JVM就会把这个线程放到这个对象的琐池中。 <br />
3、 其它的阻塞状态：当前线程执行了sleep()方法，或者调用了其它线程的join()方法，或者发出了I/O请求时，就会进入这个状态中。 <br />
<br />
死亡状态：当线程退出了run()方法，就进入了死亡状态，该线程结束了生命周期。 <br />
或者正常退出 <br />
或者遇到异常退出 <br />
Thread类的isAlive()方法判断一个线程是否活着，当线程处于死亡状态或者新建状态时，该方法返回false,在其余的状态下，该方法返回true. <br />
<br />
线程调度 <br />
线程调度模型：分时调度模型和抢占式调度模型 <br />
JVM采用抢占式调度模型。 <br />
所谓的多线程的并发运行，其实是指宏观上看，各个线程轮流获得CPU的使用权，分别执行各自的任务。 <br />
（线程的调度不是跨平台，它不仅取决于java虚拟机，它还依赖于操作系统） <br />
<br />
如果希望明确地让一个线程给另外一个线程运行的机会，可以采取以下的办法之一 <br />
1、 调整各个线程的优先级 <br />
2、 让处于运行状态的线程调用Thread.sleep()方法 <br />
3、 让处于运行状态的线程调用Thread.yield()方法 <br />
4、 让处于运行状态的线程调用另一个线程的join()方法 <br />
<br />
调整各个线程的优先级 <br />
Thread类的setPriority(int)和getPriority()方法分别用来设置优先级和读取优先级。 <br />
如果希望程序能够移值到各个操作系统中，应该确保在设置线程的优先级时，只使用MAX_PRIORITY、NORM_PRIORITY、MIN_PRIORITY这3个优先级。 <br />
<br />
线程睡眠：当线程在运行中执行了sleep()方法时，它就会放弃CPU，转到阻塞状态。 <br />
线程让步：当线程在运行中执行了Thread类的yield()静态方法时，如果此时具有相同优先级的其它线程处于就绪状态，那么yield()方法将把当前运行的线程放到运行池中并使另一个线程运行。如果没有相同优先级的可运行线程，则yield()方法什么也不做。 <br />
Sleep()方法和yield()方法都是Thread类的静态方法，都会使当前处于运行状态的线程放弃CPU，把运行机会让给别的线程，两者的区别在于： <br />
1、sleep()方法会给其他线程运行的机会，而不考虑其他线程的优先级，因此会给较低线程一个运行的机会；yield()方法只会给相同优先级或者更高优先级的线程一个运行的机会。 <br />
2、当线程执行了sleep(long millis)方法后，将转到阻塞状态，参数millis指定睡眠时间；当线程执行了yield()方法后，将转到就绪状态。 <br />
3、sleep()方法声明抛出InterruptedException异常，而yield()方法没有声明抛出任何异常 <br />
4、sleep()方法比yield()方法具有更好的移植性 <br />
<br />
等待其它线程的结束：join() <br />
当前运行的线程可以调用另一个线程的 join()方法，当前运行的线程将转到阻塞状态，直到另一个线程运行结束，它才恢复运行。 <br />
<br />
定时器Timer:在JDK的java.util包中提供了一个实用类Timer, 它能够定时执行特定的任务。 <br />
<br />
线程的同步 <br />
原子操作：根据Java规范，对于基本类型的赋值或者返回值操作，是原子操作。但这里的基本数据类型不包括long和double, 因为JVM看到的基本存储单位是32位，而long 和double都要用64位来表示。所以无法在一个时钟周期内完成。 <br />
<br />
自增操作（++）不是原子操作，因为它涉及到一次读和一次写。 <br />
<br />
原子操作：由一组相关的操作完成，这些操作可能会操纵与其它的线程共享的资源，为了保证得到正确的运算结果，一个线程在执行原子操作其间，应该采取其他的措施使得其他的线程不能操纵共享资源。 <br />
<br />
同步代码块：为了保证每个线程能够正常执行原子操作，Java引入了同步机制，具体的做法是在代表原子操作的程序代码前加上synchronized标记，这样的代码被称为同步代码块。 <br />
<br />
同步锁：每个JAVA对象都有且只有一个同步锁，在任何时刻，最多只允许一个线程拥有这把锁。 <br />
<br />
当一个线程试图访问带有synchronized(this)标记的代码块时，必须获得 this关键字引用的对象的锁，在以下的两种情况下，本线程有着不同的命运。 <br />
1、 假如这个锁已经被其它的线程占用，JVM就会把这个线程放到本对象的锁池中。本线程进入阻塞状态。锁池中可能有很多的线程，等到其他的线程释放了锁，JVM就会从锁池中随机取出一个线程，使这个线程拥有锁，并且转到就绪状态。 <br />
2、 假如这个锁没有被其他线程占用，本线程会获得这把锁，开始执行同步代码块。 <br />
（一般情况下在执行同步代码块时不会释放同步锁，但也有特殊情况会释放对象锁 <br />
如在执行同步代码块时，遇到异常而导致线程终止，锁会被释放；在执行代码块时，执行了锁所属对象的wait()方法，这个线程会释放对象锁，进入对象的等待池中） <br />
<br />
线程同步的特征： <br />
1、 如果一个同步代码块和非同步代码块同时操作共享资源，仍然会造成对共享资源的竞争。因为当一个线程执行一个对象的同步代码块时，其他的线程仍然可以执行对象的非同步代码块。（所谓的线程之间保持同步，是指不同的线程在执行同一个对象的同步代码块时，因为要获得对象的同步锁而互相牵制） <br />
2、 每个对象都有唯一的同步锁 <br />
3、 在静态方法前面可以使用synchronized修饰符。 <br />
4、 当一个线程开始执行同步代码块时，并不意味着必须以不间断的方式运行，进入同步代码块的线程可以执行Thread.sleep()或者执行Thread.yield()方法，此时它并不释放对象锁，只是把运行的机会让给其他的线程。 <br />
5、 Synchronized声明不会被继承，如果一个用synchronized修饰的方法被子类覆盖，那么子类中这个方法不在保持同步，除非用synchronized修饰。 <br />
<br />
线程安全的类： <br />
1、 这个类的对象可以同时被多个线程安全的访问。 <br />
2、 每个线程都能正常的执行原子操作，得到正确的结果。 <br />
3、 在每个线程的原子操作都完成后，对象处于逻辑上合理的状态。 <br />
<br />
释放对象的锁： <br />
1、 执行完同步代码块就会释放对象的锁 <br />
2、 在执行同步代码块的过程中，遇到异常而导致线程终止，锁也会被释放 <br />
3、 在执行同步代码块的过程中，执行了锁所属对象的wait()方法，这个线程会释放对象锁，进入对象的等待池。 <br />
<br />
死锁 <br />
当一个线程等待由另一个线程持有的锁，而后者正在等待已被第一个线程持有的锁时，就会发生死锁。JVM不监测也不试图避免这种情况，因此保证不发生死锁就成了程序员的责任。 <br />
<br />
如何避免死锁 <br />
一个通用的经验法则是：当几个线程都要访问共享资源A、B、C 时，保证每个线程都按照同样的顺序去访问他们。 <br />
<br />
线程通信 <br />
Java.lang.Object类中提供了两个用于线程通信的方法 <br />
1、 wait():执行了该方法的线程释放对象的锁，JVM会把该线程放到对象的等待池中。该线程等待其它线程唤醒 <br />
2、 notify():执行该方法的线程唤醒在对象的等待池中等待的一个线程，JVM从对象的等待池中随机选择一个线程，把它转到对象的锁池中。<br />
<br />
<br />
<br />
<br />
<br />
<img src ="http://www.blogjava.net/jzone/aggbug/287371.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jzone/" target="_blank">Gavin.lee</a> 2009-07-19 21:10 <a href="http://www.blogjava.net/jzone/articles/287371.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>多线程设计方法</title><link>http://www.blogjava.net/jzone/articles/287040.html</link><dc:creator>Gavin.lee</dc:creator><author>Gavin.lee</author><pubDate>Thu, 16 Jul 2009 14:32:00 GMT</pubDate><guid>http://www.blogjava.net/jzone/articles/287040.html</guid><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 一：继承Thread，重载run方法package&nbsp;com.Gavin.threaddesign;/**&nbsp;*//**&nbsp;*&nbsp;**********************************************&nbsp;*&nbsp;@description&nbsp;继承Thread&nbsp;类的多线程程序&nbsp;设计方法&nb...&nbsp;&nbsp;<a href='http://www.blogjava.net/jzone/articles/287040.html'>阅读全文</a><img src ="http://www.blogjava.net/jzone/aggbug/287040.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jzone/" target="_blank">Gavin.lee</a> 2009-07-16 22:32 <a href="http://www.blogjava.net/jzone/articles/287040.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>