<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>中文 &#187; johee</title>
	<atom:link href="http://software.intel.com/zh-cn/blogs/author/johee/feed/" rel="self" type="application/rss+xml" />
	<link>http://software.intel.com/zh-cn/blogs</link>
	<description></description>
	<lastBuildDate>Sat, 26 May 2012 06:34:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
		<item>
		<title>Java 多线程</title>
		<link>http://software.intel.com/zh-cn/blogs/2010/07/05/java-6/</link>
		<comments>http://software.intel.com/zh-cn/blogs/2010/07/05/java-6/#comments</comments>
		<pubDate>Mon, 05 Jul 2010 09:51:51 +0000</pubDate>
		<dc:creator>johee</dc:creator>
				<category><![CDATA[博客征文专栏]]></category>
		<category><![CDATA[并行计算]]></category>
		<category><![CDATA[intel]]></category>

		<guid isPermaLink="false">http://software.intel.com/zh-cn/blogs/2010/07/05/java-6/</guid>
		<description><![CDATA[  1. 创建线程有两种方式： 1）扩展java.lang.Thread类 public class ThreadTest extends Thread{ } 2）实现Runnable接口 public class ThreadTest implements Runnable{ } 2. Thread类代表线程类，有两个最主要的方法： 1）run() 包含线程运行时所执行的代码。 用户的线程类只需要继承Thread类，覆盖Thread类的run()方法即可。在Thread类中的run()方法没有招聘任何异常，所以Thread子类的run()方法也不能声明招聘任何异常。 2）start() 用于启动线程。 3．线程的运行过程： 1）主线程与用户自定义的线程并发运行 2）多个线程共享一个对象的实例变量 3）不要随便覆盖Thread类的start()方法，假如一定要覆盖，就在重新定义的start()方法首语句中调用super.start()方法。 4）一个线程只能被启动一次 4．线程的状态转换： 1）新建状态 用new语句创建的线程对象处于新建状态，此时它和其他Java对象一样，仅仅在堆区中被分配了内存。 2）就绪状态 当一个线程对象创建后，其他线程调用它的start()方法，该线程就进入就绪状态，JVM会为它创建方法调用栈和程序计数器。处于这个状态的线程位于可运行池中，等待获得CPU的使用权。 3）运行状态 处于这个状态的线程占用CPU，执行程序代码。在并发运行环境中，如果计算机只有一个CPU，那么任何时刻只会有一个线程处于这个状态。如果计算机有多个CPU，那么同一时刻可以让几个线程占用不同的CPU，使它们都处于运行状态。只有牌就绪状态的线程才有机会转到运行状态。 4）阻塞状态 阻塞状态是指线程因为某些原因放弃CPU，暂时停止运行。当线程处于阻塞状态时，JVM不会给线程分配CPU，直到线程重新进入就绪状态，它才有机会转到运行状态。 阻塞状态可分为以下3种 1))位于对象等等池中的阻塞状态：当线程牌运行状态时，如果执行了某个对象的wait()方法，JVM就会把线程放到这个对象的等待池中。 2))位于对象锁池中的阻塞状态：当线程牌运行状态，试图获得某个对象的同步锁时，如果该对象的同步锁已经被其他线程占用，JVM就会把这个线程放到这个对旬的锁池中。 3))其他阻塞状态：当前线程执行了sleep()方法，或者调用了其他线程的join()方法，或者发出了I/O请求时，就会进入这个状态。 当一个线程执行System.out.println()或者System.in.read()方法时，就会发出一个I/O请求，该线程放弃CPU，进入阻塞状态，直到I/O处理完毕，该线程才会恢复运行。 5）死亡状态 当线程退出run()方法时，就进入死亡状态，该线程结束生命周期。线程有可能是正常执行完run()方法而退出，也有可能是遇到异常而退出。不管线程正常结束还是异常结束，都不会对其他其他线程造成影响。 Thread类的isAlive()方法判断一个线程是否活着，当线程处于死亡状态或者新建状态时，该方法返回false,在其余状态下，该方法返回true. 5.线程的调度： 有两种调度方式：分时调度模型和抢占式调度模型。 分时调度模型是指让所有线程轮流获得CPU的使用权，并且平均分配每个线程占用CPU的时间片。 Java虚拟机采用抢占式高度模型，是指优先让可运行池中优先级高的线程占用CPU，如果可运行池中线程的优先级相同，那么就随机选择一个线程，使其占用CPU。处于运行状态的线程会一直运行，直至它不得不放弃CPU。 线程的调度不是跨平台的，它不仅取决于JVM,还依赖于操作系统。 6．Thread类的setPriority(int)和getPriority()方法分别用来设置优先级和读取优先级。 1）MAX_PRIORITY:取值为10，表示最高优先级 2）MIN_PRIORITY:取值为1，表示最低优先级 3）NORM_PRIORITY:取值为5，表示默认的优先级 [...]]]></description>
			<content:encoded><![CDATA[<p> </p>
<p>1. 创建线程有两种方式：</p>
<p>1）扩展java.lang.Thread类</p>
<p>public class ThreadTest extends Thread{ }</p>
<p>2）实现Runnable接口</p>
<p>public class ThreadTest implements Runnable{ }</p>
<p>2. Thread类代表线程类，有两个最主要的方法：</p>
<p>1）run() 包含线程运行时所执行的代码。</p>
<p>用户的线程类只需要继承Thread类，覆盖Thread类的run()方法即可。在Thread类中的run()方法没有招聘任何异常，所以Thread子类的run()方法也不能声明招聘任何异常。</p>
<p>2）start() 用于启动线程。</p>
<p>3．线程的运行过程：</p>
<p>1）主线程与用户自定义的线程并发运行</p>
<p>2）多个线程共享一个对象的实例变量</p>
<p>3）不要随便覆盖Thread类的start()方法，假如一定要覆盖，就在重新定义的start()方法首语句中调用super.start()方法。</p>
<p>4）一个线程只能被启动一次</p>
<p>4．线程的状态转换：</p>
<p>1）新建状态</p>
<p>用new语句创建的线程对象处于新建状态，此时它和其他Java对象一样，仅仅在堆区中被分配了内存。</p>
<p>2）就绪状态</p>
<p>当一个线程对象创建后，其他线程调用它的start()方法，该线程就进入就绪状态，JVM会为它创建方法调用栈和程序计数器。处于这个状态的线程位于可运行池中，等待获得CPU的使用权。</p>
<p>3）运行状态</p>
<p>处于这个状态的线程占用CPU，执行程序代码。在并发运行环境中，如果计算机只有一个CPU，那么任何时刻只会有一个线程处于这个状态。如果计算机有多个CPU，那么同一时刻可以让几个线程占用不同的CPU，使它们都处于运行状态。只有牌就绪状态的线程才有机会转到运行状态。</p>
<p>4）阻塞状态</p>
<p>阻塞状态是指线程因为某些原因放弃CPU，暂时停止运行。当线程处于阻塞状态时，JVM不会给线程分配CPU，直到线程重新进入就绪状态，它才有机会转到运行状态。</p>
<p>阻塞状态可分为以下3种</p>
<p>1))位于对象等等池中的阻塞状态：当线程牌运行状态时，如果执行了某个对象的wait()方法，JVM就会把线程放到这个对象的等待池中。</p>
<p>2))位于对象锁池中的阻塞状态：当线程牌运行状态，试图获得某个对象的同步锁时，如果该对象的同步锁已经被其他线程占用，JVM就会把这个线程放到这个对旬的锁池中。</p>
<p>3))其他阻塞状态：当前线程执行了sleep()方法，或者调用了其他线程的join()方法，或者发出了I/O请求时，就会进入这个状态。</p>
<p>当一个线程执行System.out.println()或者System.in.read()方法时，就会发出一个I/O请求，该线程放弃CPU，进入阻塞状态，直到I/O处理完毕，该线程才会恢复运行。</p>
<p>5）死亡状态</p>
<p>当线程退出run()方法时，就进入死亡状态，该线程结束生命周期。线程有可能是正常执行完run()方法而退出，也有可能是遇到异常而退出。不管线程正常结束还是异常结束，都不会对其他其他线程造成影响。</p>
<p>Thread类的isAlive()方法判断一个线程是否活着，当线程处于死亡状态或者新建状态时，该方法返回false,在其余状态下，该方法返回true.</p>
<p>5.线程的调度：</p>
<p>有两种调度方式：分时调度模型和抢占式调度模型。</p>
<p>分时调度模型是指让所有线程轮流获得CPU的使用权，并且平均分配每个线程占用CPU的时间片。</p>
<p>Java虚拟机采用抢占式高度模型，是指优先让可运行池中优先级高的线程占用CPU，如果可运行池中线程的优先级相同，那么就随机选择一个线程，使其占用CPU。处于运行状态的线程会一直运行，直至它不得不放弃CPU。</p>
<p>线程的调度不是跨平台的，它不仅取决于JVM,还依赖于操作系统。</p>
<p>6．Thread类的setPriority(int)和getPriority()方法分别用来设置优先级和读取优先级。</p>
<p>1）MAX_PRIORITY:取值为10，表示最高优先级</p>
<p>2）MIN_PRIORITY:取值为1，表示最低优先级</p>
<p>3）NORM_PRIORITY:取值为5，表示默认的优先级</p>
<p>如果希望程序能移植到各个操作系统中，应该确保在设置线程的优先级时，只使用MAX_PRIORITY、MIN_PRIORITY、NORM_PRIORITY这三个优先级。这样才能保证在不同的操作系统中，对同样优先级的线程采用同样的调度方式。</p>
<p>7．sleep()方法与yield()方法的区别：</p>
<p>1）sleep()方法会给其他线程运行的机会，而不考虑其他线程的优先级，因此会给较低优先级线程一个运行的机会；yield()方法只会给相同优先级或者更高优先级的线程一个运行的机会。</p>
<p>2）当线程执行了sleep()方法后，将转到阻塞状态；当线程执行了yield()方法后，将转到就绪状态。</p>
<p>3）sleep()方法声明抛出InterruptedException异常，而yield()方法没有声明招聘任何异常。</p>
<p>4）sleep()方法比yield()方法具有更好的可移植性。</p>
<p>8．等待其他线程结束：join()方法</p>
<p>当前运行的线程可以调用另一个线程的join()方法，当前运行的线程将转到阻塞状态，直至另一个线程运行结束，它才会恢复运行（确切的意思是指线程从阻塞状态转到就绪状态）。</p>
<p>9．定时器Timer</p>
<p>Timer timer=new Timer(true);</p>
<p>TimerTask task=new TimerTask(){ }</p>
<p>timer.schedule(task,10,500);//定时器将在10毫秒后开始执行task任务，以后每隔//500毫秒重复执行一次task任务。</p>
<p>timer.schedule(task,10);//只执行一次task任务。</p>
<p>10．同步代码块</p>
<p>为了保证每个线程能正常执行原子操作，Java引入了同步机制，具体做法是在代表原子操作的程序代码前加上synchronized标记，这样的代码被称为同步代码块。</p>
<p>有两种方式加代码锁：</p>
<p>1） 直接在方法前加synchronized标记，</p>
<p>public synchronized void add(){... }</p>
<p>2) 在方法内形成synchronized标记的代码块</p>
<p>public void add(){synchronized(this){... }}</p>
<p>取得对象锁：</p>
<p>1） 假如这个锁已经被其他线程占用，JVM就会把这个消费者线程放到Stack对象的锁池中，消费者线程进入阻塞状态。在Stack对象的锁池中可能会有许多等待锁的线程。等到其他线程释放了锁，JVM会从锁池中随机取出一个线程，使这个线程拥有锁，并且转到就绪状态。</p>
<p>2） 假如这个锁没有被其他线程占用，消费者线程就会获得这把锁，开始执行同步代码块。在一般情况下，消费者线程只有执行完同步代码块，才会释放锁，使得其他线程能够获得锁。</p>
<p>释放对象锁：</p>
<p>1） 执行完同步代码块，就会释放锁。</p>
<p>2） 在执行同步代码块的过程中，遇到异常而导致线程终止，锁也会被释放。</p>
<p>3） 在执行同步代码块的过程中，执行了锁所属对象的wait()方法，这个线程会释放锁，进入对象的等待池。</p>
<p>4） 在执行同步代码块的过程中，执行了锁所属对象的notify()方法后，JVM会从对象的等待池中随机选择一个线程，把它转到对象的锁池中。</p>
<p>线程同步的特征：</p>
<p>1） 如果一个同步代码块和非同步代码块同时操纵共享资源，仍然会造成对共享资源的竞争。因为当一个线程执行一个对象的同步代码块时，其他线程仍然可以执行对象的非同步代码块。</p>
<p>2） 每一个对象都有惟一的同步锁。</p>
<p>3） 在静态方法前面也可以使用synchronized修饰符。</p>
<p>4） 当一个线程开始执行同步代码块时，并不意味着必须以不中断的方式运行。进入同步代码块中的线程也可以执行Thread.sleep()或者执行Thread.yield()方法，此时它并没有释放锁，只是把运行机会（即CPU）让给了其他的线程。</p>
<p>5） synchronized声明不会被继承.</p>
<p>11．死锁：</p>
<p>当一个线程等等由另一个线程持有的锁，而后者正在等待已被第一个线程持有的锁时，就会发生死锁。JVM不监测也不试图避免这种情况，因此保证不发生死锁就成了程序员的责任。</p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/zh-cn/blogs/2010/07/05/java-6/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

