JAVA线程简介

Thread是程序中的执行线程。Java虚拟机允许应用程序并发地运行多个执行线程。
每个线程都有一个优先级,高优先级线程的执行优先于低优先级线程。
线程可以是守护线程或非守护线程
当某个线程中运行的代码创建一个新Thread对象时,该新线程的初始优先级被设定为创建线程的优先级,
并且默认情况下,当且仅当创建它的线程是守护线程时,新线程才是守护程序
Java虚拟机启动时,通常都会有单个非守护线程(它通常会调用某个指定类的main方法)。
<wbr style="line-height:25px"><span style="line-height:25px">Java虚拟机会继续执行线程,直到下列任一情况出现时为止:</span><br style="line-height:25px"><span style="color:#000080; line-height:25px">*调用了</span><span style="color:#0000ff; line-height:25px">Runtime</span><span style="color:#000080; line-height:25px">类的</span><span style="color:#0000ff; line-height:25px">exit</span><span style="color:#000080; line-height:25px">方法,并且安全管理器允许退出操作发生。<br style="line-height:25px"> *非守护线程的所有线程都已停止运行,无论是通过从对run方法的调用中返回,还是通过抛出一个传播到run方法之外的异常<wbr style="line-height:25px">。</wbr></span><br style="line-height:25px"><wbr style="line-height:25px"><span style="line-height:25px">守护线程:</span><span style="color:#000080; line-height:25px">它是指只要程序还在运行,它就应该在后台提供某种公共服务的线程,但它不属于程序的核心部分<wbr style="line-height:25px">。<br style="line-height:25px"> 例如:main的线程就属于非守护线程。若要创建守护线程,我们在它启动之前,调用setDaemon()方法来设置。<br style="line-height:25px"> 关于守护线程更多参考《<strong><a title="阅读全文" target="_blank" href="http://hubingforever.blog.163.com/blog/static/171040579201071243532363/" style="color:rgb(207,121,28); line-height:25px; text-decoration:none">守护线程</a></strong></wbr></span><span style="color:#000080; line-height:25px">》</span><br style="line-height:25px"><span style="color:#003366; line-height:25px">创建新执行线程有两种方法。一种方法是将类声明为Thread的子类。该子类应重写Thread类的run方法。<br style="line-height:25px"> 接下来可以分配并启动该子类的实例</span>。例如,计算大于某一规定值的质数的线程可以写成:<br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">class</span><span style="color:#3366ff; line-height:25px"></span><span style="color:#ff6600; line-height:25px">PrimeThread</span><span style="color:#800000; line-height:25px">extends</span><span style="color:#3366ff; line-height:25px"></span><span style="color:#ff9900; line-height:25px">Thread</span><span style="color:#3366ff; line-height:25px">{<br style="line-height:25px"> longminPrime;<br style="line-height:25px"> PrimeThread(longminPrime){<br style="line-height:25px"> this.minPrime=minPrime;<br style="line-height:25px"> }<br style="line-height:25px"><br style="line-height:25px"></span><span style="color:#993300; line-height:25px">publicvoid</span><span style="color:#3366ff; line-height:25px"></span><span style="color:#ff6600; line-height:25px">run</span><span style="color:#3366ff; line-height:25px">(){<br style="line-height:25px"> //computeprimeslargerthanminPrime<br style="line-height:25px"> ...<br style="line-height:25px"> }<br style="line-height:25px"> }</span><br style="line-height:25px"> 然后,下列代码会创建并启动一个线程:<br style="line-height:25px"><span style="color:#3366ff; line-height:25px"> PrimeThreadp=newPrimeThread(143);<br style="line-height:25px"> p.start();</span><br style="line-height:25px"> 创建线程的另一种方法是声明实现Runnable接口的类。该类然后实现run方法。<br style="line-height:25px"> 然后可以分配该类的实例,在创建Thread时作为一个参数来传递并启动。采用这种风格的同一个例子如下所示:<br style="line-height:25px"><span style="color:#3366ff; line-height:25px"></span><span style="color:#993300; line-height:25px">class</span><span style="color:#ff6600; line-height:25px">PrimeRun</span><span style="color:#993300; line-height:25px">implements</span><span style="color:#3366ff; line-height:25px">Runnable{<br style="line-height:25px"> longminPrime;<br style="line-height:25px"> PrimeRun(longminPrime){<br style="line-height:25px"> this.minPrime=minPrime;<br style="line-height:25px"> }<br style="line-height:25px"></span><span style="color:#993300; line-height:25px">publicvoid</span><span style="color:#3366ff; line-height:25px"></span><span style="color:#ff6600; line-height:25px">run</span><span style="color:#3366ff; line-height:25px">(){<br style="line-height:25px"> //computeprimeslargerthanminPrime<br style="line-height:25px"> ...<br style="line-height:25px"> }<br style="line-height:25px"> }</span><br style="line-height:25px"> 然后,下列代码会创建并启动一个线程:<br style="line-height:25px"><span style="color:#0000ff; line-height:25px"> PrimeRunp=newPrimeRun(143);<br style="line-height:25px"> newThread(p).start();</span><br style="line-height:25px"> 每个线程都有一个标识名,多个线程可以同名。如果线程创建时没有指定标识名,就会为其生成一个新名称。<br style="line-height:25px"> 主要方法:<br style="line-height:25px"><wbr style="line-height:25px"><span style="color:#993300; line-height:25px">publicvoid</span><span style="color:#ff6600; line-height:25px">start()</span><wbr style="line-height:25px"><br style="line-height:25px"> 使该线程开始执行;Java虚拟机调用该线程的run方法。<br style="line-height:25px"> 结果是两个线程并发地运行;当前线程(从调用返回给start方法)和另一个线程(执行其run方法)。<br style="line-height:25px"> 多次启动一个线程是非法的。特别是当线程已经结束执行后,不能再重新启动。<br style="line-height:25px"> 抛出:<br style="line-height:25px"> IllegalThreadStateException-如果线程已经启动。<br style="line-height:25px"><wbr style="line-height:25px"><span style="color:#993300; line-height:25px">publicstaticvoid</span><span style="color:#ff6600; line-height:25px">yield()</span><wbr style="line-height:25px"><br style="line-height:25px"> 暂停当前正在执行的线程对象,并执行其他线程。<br style="line-height:25px"> 注意:我觉得他不一定能执行其他线程。它的本质应该是让系统再次来进行线程的调度。<br style="line-height:25px"> 那么应该也有可能该线程被调度(当然这点可能要依赖JVM的实现)。<br style="line-height:25px"><span style="color:#993300; line-height:25px">publicstaticvoid</span><span style="color:#ff6600; line-height:25px">sleep</span>(longmillis)<br style="line-height:25px"> throwsInterruptedException<br style="line-height:25px"> 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。<br style="line-height:25px"> 该线程不丢失任何监视器的所属权。<br style="line-height:25px"> 参数:<br style="line-height:25px"> millis-以毫秒为单位的休眠时间。<br style="line-height:25px"> 抛出:<br style="line-height:25px"> InterruptedException-如果任何线程中断了当前线程。当抛出该异常时,当前线程的中断状态被清除。<br style="line-height:25px"> 注意1<span style="color:#000080; line-height:25px">:<wbr style="line-height:25px">sleep不会释放对象的锁,而wait则会<wbr style="line-height:25px">。</wbr></wbr></span><br style="line-height:25px"> 注意2<span style="line-height:25px"><wbr style="line-height:25px">:</wbr></span><span style="color:#000080; line-height:25px">sleep可以被interrupt()方法中断而被唤醒。具体参考《<strong><a title="阅读全文" target="_blank" href="http://hubingforever.blog.163.com/blog/static/17104057920108154244111/" style="color:rgb(207,121,28); line-height:25px; text-decoration:none">线程的interrupt</a></strong></span><span style="color:#000080; line-height:25px">》</span><wbr style="line-height:25px"><br style="line-height:25px"><span style="color:#993300; line-height:25px">publicfinalvoid</span><span style="color:#ff6600; line-height:25px">setPriority</span>(intnewPriority)<br style="line-height:25px"> 更改线程的优先级。<br style="line-height:25px"> 首先调用线程的checkAccess方法,且不带任何参数。这可能抛出SecurityException。<br style="line-height:25px"> 在其他情况下,线程优先级被设定为指定的newPriority和该线程的线程组的最大允许优先级相比较小的一个。<br style="line-height:25px"> 参数:<br style="line-height:25px"> newPriority-要为线程设定的优先级<br style="line-height:25px"> 抛出:<br style="line-height:25px"> IllegalArgumentException-如果优先级不在MIN_PRIORITY到MAX_PRIORITY范围内。<br style="line-height:25px"> SecurityException-如果当前线程无法修改该线程。<br style="line-height:25px"> 注意1:我们可以通过调用setPriority()方法来设置线程的优先级,线程的优先级总共有10级,<br style="line-height:25px"> 但为了保证可移植性,我们最好使用MIN_PRIORITY、NORM_PRIORITY和MAX_PRIORITY。<br style="line-height:25px"><span style="color:#993300; line-height:25px">publicfinalvoid</span><span style="color:#ff6600; line-height:25px">join(</span>)<br style="line-height:25px"> throwsInterruptedException<br style="line-height:25px"><br style="line-height:25px"> 当前等待该线程终止后才继续运行。<br style="line-height:25px"><br style="line-height:25px"> 抛出:<br style="line-height:25px"> InterruptedException-如果任何线程中断了当前线程。当抛出该异常时,当前线程的中断状态被清除。<br style="line-height:25px"> 注意:<span style="color:#000080; line-height:25px">一个线程可以调用另一个线程的join()方法,主叫线程会先挂起,而等到那个线程结束后再继续运行。<br style="line-height:25px"> 我们也可以给join()方法给一个timeout参数,这样如果目标线程在期限到期后还没有结束,<br style="line-height:25px"> join()就会强制返回。而且join()方法还会被主叫线程的interrupt()方法打断。</span><br style="line-height:25px"> 其使用可参见实例1<br style="line-height:25px"> interrupt<br style="line-height:25px"><wbr style="line-height:25px"><span style="color:#993300; line-height:25px">publicvoid</span><span style="line-height:25px"></span><span style="color:#ff6600; line-height:25px">interrupt()</span><wbr style="line-height:25px"><br style="line-height:25px"> 中断线程。<br style="line-height:25px"> 如果当前线程没有中断它自己(这在任何情况下都是允许的),则该线程的checkAccess方法就会被调用,这可能抛出SecurityException。<br style="line-height:25px"> 如果线程在调用Object类的wait()、wait(long)或wait(long,int)方法,或者该类的join()、join(long)、join(long,int)、sleep(long)或sleep(long,int)方法过程中受阻,则其中断状态将被清除,它还将收到一个InterruptedException。<br style="line-height:25px"> 如果该线程在可中断的通道上的I/O操作中受阻,则该通道将被关闭,该线程的中断状态将被设置并且该线程将收到一个ClosedByInterruptException。<br style="line-height:25px"> 如果该线程在一个Selector中受阻,则该线程的中断状态将被设置,它将立即从选择操作返回,并可能带有一个非零值,就好像调用了选择器的wakeup方法一样。<br style="line-height:25px"> 如果以前的条件都没有保存,则该线程的中断状态将被设置。<br style="line-height:25px"> 中断一个不处于活动状态的线程不需要任何作用。<br style="line-height:25px"> 抛出:<br style="line-height:25px"> SecurityException-如果当前线程无法修改该线程<br style="line-height:25px"> 注意:关于interrupt()的更多内容请参考《线程interrupt》<br style="line-height:25px"><span style="line-height:25px"><wbr style="line-height:25px">已经过时的方法</wbr></span><wbr style="line-height:25px"><br style="line-height:25px"><span style="line-height:25px"><wbr style="line-height:25px">publicfinalvoidstop()</wbr></span><wbr style="line-height:25px"><br style="line-height:25px"> 已过时。该方法具有固有的不安全性。用Thread.stop来终止线程将释放它已经锁定的所有监视器<br style="line-height:25px"> (作为沿堆栈向上传播的未检查ThreadDeath异常的一个自然后果)。如果以前受这些监视器保护的任何对象都处于一种不一致的状态,<br style="line-height:25px"> 则损坏的对象将对其他线程可见,这有可能导致任意的行为。<br style="line-height:25px"> stop的许多使用都应由只修改某些变量以指示目标线程应该停止运行的代码来取代。<br style="line-height:25px"> 目标线程应定期检查该变量,并且如果该变量指示它要停止运行,则从其运行方法依次返回。<br style="line-height:25px"> 如果目标线程等待很长时间(例如基于一个条件变量),则应使用interrupt方法来中断该等待。<br style="line-height:25px"> 有关更多信息,请参阅为何不赞成使用Thread.stop、Thread.suspend和Thread.resume?。<br style="line-height:25px"> 强迫线程停止执行。<br style="line-height:25px"> 无论该线程在做些什么,它所代表的线程都被迫异常停止,并抛出一个新创建的ThreadDeath对象,作为异常。<br style="line-height:25px"> 停止一个尚未启动的线程是允许的。如果最后启动了该线程,它会立即终止。<br style="line-height:25px"> 应用程序通常不应试图捕获ThreadDeath,除非它必须执行某些异常的清除操作<br style="line-height:25px"> (注意,抛出ThreadDeath将导致try语句的finally子句在线程正式终止前执行)。<br style="line-height:25px"> 如果catch子句捕获了一个ThreadDeath对象,则重新抛出该对象很重要,因为这样该线程才会真正终止。<br style="line-height:25px"> 注意:该方法已经过时。还是用变量来控制run()函数的结束,从而控制线程的介绍比较好。<br style="line-height:25px"><span style="line-height:25px"><wbr style="line-height:25px">publicvoiddestroy()</wbr></span><wbr style="line-height:25px"><br style="line-height:25px"> 已过时。该方法最初用于破坏该线程,但不作任何清除。它所保持的任何监视器都会保持锁定状态。<br style="line-height:25px"> 不过,该方法决不会被实现。即使要实现,它也极有可能以suspend()方式被死锁。<br style="line-height:25px"> 如果目标线程被破坏时保持一个保护关键系统资源的锁,则任何线程在任何时候都无法再次访问该资源。<br style="line-height:25px"> 如果另一个线程曾试图锁定该资源,则会出现死锁。这类死锁通常会证明它们自己是“冻结”的进程。<br style="line-height:25px"> 抛出:<br style="line-height:25px"> NoSuchMethodError-始终<br style="line-height:25px"> 注意1:该方法已经过时。<br style="line-height:25px"> 注意2:该方法决不会被实现(没实现就抛异常NoSuchMethodError)。即使要实现,它也极有可能以suspend()方式被死锁<br style="line-height:25px"> publicfinalvoidsuspend()<br style="line-height:25px"> 已过时。该方法已经遭到反对,因为它具有固有的死锁倾向。<br style="line-height:25px"> 如果目标线程挂起时在保护关键系统资源的监视器上保持有锁,则在目标线程重新开始以前任何线程都不能访问该资源。<br style="line-height:25px"> 如果重新开始目标线程的线程想在调用resume之前锁定该监视器,则会发生死锁。这类死锁通常会证明自己是“冻结”的进程。<br style="line-height:25px"> 有关更多信息,请参阅为何不赞成使用Thread.stop、Thread.suspend和Thread.resume?。<br style="line-height:25px"> 挂起线程。<br style="line-height:25px"> 首先,调用线程的checkAccess方法,且不带任何参数。这可能抛出SecurityException(在当前线程中)。<br style="line-height:25px"> 如果线程处于活动状态则被挂起,且不再有进一步的活动,除非重新开始。<br style="line-height:25px"> 抛出:<br style="line-height:25px"> SecurityException-如果当前线程不能修改该线程。<br style="line-height:25px"> 另请参见:<br style="line-height:25px"> checkAccess()<br style="line-height:25px"> 注意1:该方法已经过时。<br style="line-height:25px"> 注意2:它具有固有的死锁倾向。线程使用suspend()挂起时,仍然保持有锁<br style="line-height:25px"><span style="line-height:25px"><wbr style="line-height:25px">publicfinalvoidresume()</wbr></span><wbr style="line-height:25px"><br style="line-height:25px"> 已过时。该方法只与suspend()一起使用,但suspend()已经遭到反对,因为它具有死锁倾向。<br style="line-height:25px"> 有关更多信息,请参阅为何不赞成使用Thread.stop、Thread.suspend和Thread.resume?。<br style="line-height:25px"> 重新开始挂起的进程。<br style="line-height:25px"> 首先,调用线程的checkAccess方法,且不带任何参数。这可能抛出SecurityException(在当前线程中)。<br style="line-height:25px"> 如果线程处于活动状态但被挂起,则它会在执行过程中重新开始并允许继续活动。<br style="line-height:25px"> 抛出:<br style="line-height:25px"> SecurityException-如果当前线程不能修改该线程。<br style="line-height:25px"> 注意:该方法已经过时。<br style="line-height:25px"> 共享资源:<br style="line-height:25px"> semaphore:用于线程间通信的标志对象,我们可以通过使用synchronized关键字作为函数定义的前缀来保护代码。<br style="line-height:25px"> 原子操作:在成员变量前面加上volatile关键字。<br style="line-height:25px"> 关键段:有时只需要防止多个线程同时访问方法中的某一部分,我们可以使用synchronized关键段。如下:<br style="line-height:25px"> synchronized(syncObject){<br style="line-height:25px"> ?//Thiscodecanbeaccessed<br style="line-height:25px"> ?//byonlyonethreadatatime<br style="line-height:25px"> }<br style="line-height:25px"><span style="line-height:25px"><wbr style="line-height:25px">线程的状态,有如下四种</wbr></span><wbr style="line-height:25px">:<br style="line-height:25px"><wbr style="line-height:25px"><span style="color:#993300; line-height:25px">New</span><wbr style="line-height:25px">:已经创建完毕,但还没有开始启动。<br style="line-height:25px"><wbr style="line-height:25px"><span style="color:#993300; line-height:25px">Runnable</span><wbr style="line-height:25px">:只要cpu分给其时间,就能运行。<br style="line-height:25px"><wbr style="line-height:25px"><span style="color:#993300; line-height:25px">Dead</span><wbr style="line-height:25px">:中止线程的正确的方法是退出run()方法。<br style="line-height:25px"><wbr style="line-height:25px"><span style="color:#993300; line-height:25px">Blocked</span><wbr style="line-height:25px">:就本身而言,是可运行的,但因为某种原因而被阻塞。除非重新进入Runnable否则,<wbr style="line-height:25px">cpu不会分给其时间<wbr style="line-height:25px">。<br style="line-height:25px"><wbr style="line-height:25px">关于synchronized,wait(),notify()和notifyall()方法请参阅《<strong><a title="阅读全文" target="_blank" href="http://hubingforever.blog.163.com/blog/static/1710405792010816493882/" style="color:rgb(207,121,28); line-height:25px; text-decoration:none">线程中的wait和notify方法</a></strong>》<wbr style="line-height:25px"><br style="line-height:25px"> 实例1:<br style="line-height:25px"><wbr style="line-height:25px">join的使用<wbr style="line-height:25px"><br style="line-height:25px"><span style="color:#993300; line-height:25px">staticvoid</span>JoinDemo()<br style="line-height:25px"> {<br style="line-height:25px"> intn=3;<br style="line-height:25px"> Threadthreads[]=newThread[n];<br style="line-height:25px"><span style="color:#993300; line-height:25px">for</span>(inti=0;i&lt;n;i++)<br style="line-height:25px"> {<br style="line-height:25px"> if(i==0)<br style="line-height:25px"> threads<wbr style="line-height:25px">=newThread(newJoinDemoRunnable());<br style="line-height:25px"> else<br style="line-height:25px"><span style="line-height:25px; font-style:normal">threads<wbr style="line-height:25px">=newThread(newJoinDemoRunnable(threads[i-1]));<br style="line-height:25px"> }<br style="line-height:25px"><span style="color:#993300; line-height:25px">for</span>(inti=0;i&lt;n;i++)<br style="line-height:25px"> {<br style="line-height:25px"> threads</wbr></span><span style="line-height:25px; font-style:normal"><wbr style="line-height:25px">.start();<br style="line-height:25px"> }<br style="line-height:25px"> }<br style="line-height:25px"><span style="color:#993300; line-height:25px">class</span>JoinDemoRunnable<span style="color:#993300; line-height:25px">implements</span>Runnable<br style="line-height:25px"> {<br style="line-height:25px"> longid=0;<br style="line-height:25px"> staticlongcount=0;<br style="line-height:25px"> Threadt;<br style="line-height:25px"> JoinDemoRunnable()<br style="line-height:25px"> {<br style="line-height:25px"> this(null);<br style="line-height:25px"> }<br style="line-height:25px"> JoinDemoRunnable(Threadt)<br style="line-height:25px"> {<br style="line-height:25px"> id=count++;<br style="line-height:25px"> this.t=t;<br style="line-height:25px"> }<br style="line-height:25px"> booleanblRun=true;<br style="line-height:25px"><span style="color:#993300; line-height:25px">publicvoid</span><span style="color:#ff6600; line-height:25px">run</span>()<br style="line-height:25px"> {intcnt=0;<br style="line-height:25px"> while(blRun)<br style="line-height:25px"> {<br style="line-height:25px"> if(t!=null)<br style="line-height:25px"> {<br style="line-height:25px"> try<br style="line-height:25px"> {t.join();<br style="line-height:25px"> }catch(InterruptedExceptione)<br style="line-height:25px"> {<br style="line-height:25px"> e.printStackTrace();<br style="line-height:25px"> }<br style="line-height:25px"> }<br style="line-height:25px"> System.out.println(id+"run"+cnt);<br style="line-height:25px"> cnt++;<br style="line-height:25px"> if(cnt==2)<br style="line-height:25px"> {<br style="line-height:25px"> blRun=false;<br style="line-height:25px"> }<br style="line-height:25px"> }<br style="line-height:25px"> System.out.println("thread"+id+" exit");<br style="line-height:25px"> }<br style="line-height:25px"> }</wbr></span><br style="line-height:25px"><span style="line-height:25px"><wbr style="line-height:25px">结果</wbr></span><wbr style="line-height:25px">:<br style="line-height:25px"><span style="color:#3366ff; line-height:25px">0run0<br style="line-height:25px"> 0run1<br style="line-height:25px"> thread0 exit<br style="line-height:25px"> 1run0<br style="line-height:25px"> 1run1<br style="line-height:25px"> thread1 exit<br style="line-height:25px"> 2run0<br style="line-height:25px"> 2run1<br style="line-height:25px"> thread2 exit</span></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值