1.Thread API
1. public final void join() throws InterruptedException { ->Waits for this thread to die
2.public final synchronized void join(long millis) throws InterruptedException { ->Waits at most {@code millis} milliseconds for this thread to die. A timeout of {@code 0} means to wait forever. {@link Object#wait}
3.public void interrupt() -> Interrupts this thread -> If this thread is blocked in an invocation of the {@linkObject#wait() wait()}, {@link Object#wait(long) wait(long)}, or {@link Object#wait(long, int) wait(long, int)} methods of the {@link Object} class, or of the {@link #join()}, {@link #join(long)}, {@link #join(long, int)}, {@link #sleep(long)}, or {@link #sleep(long, int)},methods of this class, then its interrupt status will be cleared and it will receive an {@link InterruptedException}. ->If this thread is blocked in an I/O operation upon an {@link java.nio.channels.InterruptibleChannel </code>interruptible channel<code>} then the channel will be closed, the thread's interrupt status will be set, and the thread will receive a {@link java.nio.channels.ClosedByInterruptException}. -> If this thread is blocked in a {@link java.nio.channels.Selector}then the thread's interrupt status will be set and it will return immediately from the selection operation, possibly with a non-zero value, just as if the selector's {@link java.nio.channels.Selector#wakeup wakeup} method were invoked.
2.Object API 1.public final void wait() throws InterruptedException ->Causes the current thread to wait until another thread invokes the {@link java.lang.Object#notify()} method or the{@link java.lang.Object#notifyAll()} method for this object. In other words, this method behaves exactly as if it simply performs the call {@code wait(0)}. ->The current thread must own this object's monitor. The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object's monitor to wake up either through a call to the {@code notify} method or the{@code notifyAll} method. The thread then waits until it can re-obtain ownership of the monitor and resumes execution.
2.public final native void notify() ->Wakes up a single thread that is waiting on this object's monitor. If any threads are waiting on this object, one of them is chosen to be awakened.
3.多线程之间协作 1.Object.wait()在释放CPU同时,释放了对象锁的控制;
2.Obj.wait(),与Obj.notify()必须要与synchronized(Obj)一起使用,也就是wait,与notify是针对已经获取了Obj锁进行操作,从语法角度来说就是Obj.wait(),Obj.notify必须在synchronized(Obj){...}语句块内。从功能上来说wait就是说线程在获取对象锁后,主动释放对象锁,同时本线程休眠。直到有其它线程调用对象的notify()唤醒该线程,才能继续获取对象锁,并继续执行; 3.a.调用obj.wait()后,线程A就释放了obj的锁,否则线程B无法获得obj锁,也就无法在synchronized(obj) {...} 代码段内唤醒A b.当obj.wait()方法返回后,线程A需要再次获得obj锁,才能继续执行 c.如果A1,A2,A3都在obj.wait(),则B调用obj.notify()只能唤醒A1,A2,A3中的一个,JVM决定 d.obj.notifyAll()则能全部唤醒A1,A2,A3,但是要继续执行obj.wait()的下一条语句,必须获得obj锁,因此,A1,A2,A3只有一个有机会获得锁继续执行如A1,其余的需要等待A1释放obj锁之后才能继续执行 e.当B调用obj.notify/notifyAll的时候,B正持有obj锁,因此,A1,A2,A3虽被唤醒,但是仍无法获得obj锁。直到B退出synchronized块,释放obj锁后A1,A2,A3中的一个才有机会获得锁继续执行
4.Java的synchronized类似于操作系统概念中的互斥内存块->JAVA中对象内存锁->线程获取该内存锁后,其它线程无法访问该内存->(static(所有对象共享的内存)和对象的区别) 5.当一个线程请求其它的线程已经占有的锁时,请求线程将被阻塞。然而内部锁是可重进入的,因此线程在试图获得它自己占用的锁时请求会成功->重进入的实现是通过为每一个锁关联一个请求计数器和一个占有他的线程->当计数为0时,认为锁是未被占用的->线程请求一个未被占有的锁时候,JVM将记录锁的占有者,并且将请求计数设置为1->如果同一个线程再次请求这个锁,计数将递增->每次占用线程退出语句块时,计数器值将递减,直到计数器达到0时候,锁被释放.4.方法理解 1.join->A线程中调用->B线程的join方法B.join()->B线程继续运行,A线程停止(进入阻塞状态)->等B运行完毕A再继续运行,中途B线程不受影响->A线程停止的位置就在调用join方法处->后续代码不执行->要等B完了以后再执行-> ->join,合并->调用b.join->b线程合并到a线程->a线程等待b线程运行完再运行.(landon理解:之所以称为join,合并->将t.join的线程t合并到调用的当前线程->因为合并了t->所以要先执行t(相当于在当前线程的执行过程中插播了一段t[合并了t]))->
2.sleep-> 1.public static native void sleep(long millis) throws InterruptedException->静态方法-> 2.当前线程进入暂停状态->指定的sleep时间内都不会获得执行-> 3.可以使优先级低的线程 | 同优先级的线程 | 高优先级的线程 获得执行的机会(是否取决于当前线程的优先级) 3.yield-> 1.public static native void yield()->静态方法-> 2.线程让步->如果具有相同优先级的其他线程处于就绪状态->yield()方法将把当前运行的线程放到可运行池中并使另一个线程运行->如果没有相同优先级的可运行进程->yield什么都不做-> 3.yield->使当前线程重新回到可执行状态->执行yield()的线程有可能在进入到可运行状态后->马上又被运行->
4.interrupt-> 1.interrupt->不会中断一个正在运行的线程->这一方法实际上完成的是->在线程受到阻塞时抛出一个中断信号->这样线程就得以退出阻塞的状态->如果线程被Object.wait, Thread.join和Thread.sleep三种方法之一阻塞->它将接收到一个中断异常(InterruptedException)->从而提早地终结被阻塞状态->
2.线程被上述几种方法阻塞->正确的停止线程方式是设置共享变量->并调用interrupt()(注意变量应该先设置)->如果线程没有被阻塞,这时调用interrupt()将不起作用->否则线程就将得到异常(该线程必须事先预备好处理此状况->try/catch(InterruptedException)),接着逃离阻塞状态->在任何一种情况中,最后线程都将检查共享变量然后再停止-> (landon理解:之前我停止线程的方法是向主线程消息队列投递一个停止消息->即不通过多线程的方式->而是全部通过单线程消息队列投递消息->然后在单线程消息处理器中将stopFlag置为true) 3.public final void join() throws InterruptedException public static native void sleep(long millis) throws InterruptedException public final void join() throws InterruptedException LinkedBlockingQueue#public E take() throws InterruptedException-> public final void wait() throws InterruptedException ->目前上述方法在其线程上调用interrupt方法->都会抛出InterruptedException 4.每个线程都有一个与之相关联的 boolean 属性->用于表示线程的中断状态(interrupted status)->中断状态初始时为 false->当另一个线程通过调用 Thread.interrupt() 中断一个线程时,会出现以下两种情况之一->如果那个线程在执行一个低级可中断阻塞方法,例如 Thread.sleep()、 Thread.join() 或 Object.wait(),那么它将取消阻塞并抛出 InterruptedException->否则 interrupt() 只是设置线程的中断状态-> 在被中断线程中运行的代码以后可以轮询中断状态,看看它是否被请求停止正在做的事情->中断状态可以通过 Thread.isInterrupted() 来读取,并且可以通过一个名为 Thread.interrupted() 的操作读取和清除-> public static boolean interrupted() { return currentThread().isInterrupted(true);} 5.中断是一种协作机制->当一个线程中断另一个线程时,被中断的线程不一定要立即停止正在做的事情->相反,中断是礼貌地请求另一个线程在它愿意并且方便的时候停止它正在做的事情。有些方法,例如 Thread.sleep(),很认真地对待这样的请求,但每个方法不是一定要对中断作出响应->
6.并非所有的阻塞方法都抛出 InterruptedException。输入和输出流类会阻塞等待 I/O 完成,但是它们不抛出 InterruptedException,而且在被中断的情况下也不会提前返回(轮询中断状态?)->对于套接字 I/O,如果一个线程关闭套接字,则那个套接字上的阻塞 I/O 操作将提前结束,并抛出一个 SocketException。java.nio 中的非阻塞 I/O 类也不支持可中断 I/O,但是同样可以通过关闭通道或者请求 Selector 上的唤醒来取消阻塞操作->尝试获取一个内部锁的操作(进入一个 synchronized 块)是不能被中断的,但是 ReentrantLock 支持可中断的获取模式->
5.推荐的一篇文章
http://www.ibm.com/developerworks/cn/java/j-jtp05236.html
6.线程状态 1.New(初始状态)->t.start->Runnable(可运行状态/就绪状态)->os时间片轮转,t获得cpu时间片->Running(运行状态)->run结束->Dead(死亡状态) 2.Running(运行状态)->t2.join/sleep/io->Blocked(阻塞状态)->sleep结束/t2终止/io完成->Runnable(可运行状态/就绪状态) 3.Running(运行状态)->时间片用完/t.yield->Runnable(可运行状态/就绪状态) 4.Running(运行状态)->t线程调用o.wait->等待队列->其他线程调用o.notify/o.nonifyAll->锁池队列->拿到对象的锁->Runnable(可运行状态/就绪状态) 5.Running(运行状态)->执行synchronized块->锁池队列->拿到对象的锁->Runnable(可运行状态/就绪状态)
{@link Thread#State}
public enum State {
/** *//**
* Thread state for a thread which has not yet started.
*/
NEW,
/** *//**
* Thread state for a runnable thread. A thread in the runnable
* state is executing in the Java virtual machine but it may
* be waiting for other resources from the operating system
* such as processor.
*/
RUNNABLE,
/** *//**
* Thread state for a thread blocked waiting for a monitor lock.
* A thread in the blocked state is waiting for a monitor lock
* to enter a synchronized block/method or
* reenter a synchronized block/method after calling
* {@link Object#wait() Object.wait}.
*/
BLOCKED,
/** *//**
* Thread state for a waiting thread.
* A thread is in the waiting state due to calling one of the
* following methods:
* <ul>
* <li>{@link Object#wait() Object.wait} with no timeout</li>
* <li>{@link #join() Thread.join} with no timeout</li>
* <li>{@link LockSupport#park() LockSupport.park}</li>
* </ul>
*
* <p>A thread in the waiting state is waiting for another thread to
* perform a particular action.
*
* For example, a thread that has called <tt>Object.wait()</tt>
* on an object is waiting for another thread to call
* <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
* that object. A thread that has called <tt>Thread.join()</tt>
* is waiting for a specified thread to terminate.
*/
WAITING,
/** *//**
* Thread state for a waiting thread with a specified waiting time.
* A thread is in the timed waiting state due to calling one of
* the following methods with a specified positive waiting time:
* <ul>
* <li>{@link #sleep Thread.sleep}</li>
* <li>{@link Object#wait(long) Object.wait} with timeout</li>
* <li>{@link #join(long) Thread.join} with timeout</li>
* <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
* <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
* </ul>
*/
TIMED_WAITING,
/** *//**
* Thread state for a terminated thread.
* The thread has completed execution.
*/
TERMINATED;
}
7.守护线程 public final void setDaemon(boolean on)-> 1.->Marks this thread as either a daemon thread(守护线程) or a user thread(用户线程). The Java Virtual Machine exits when the only threads running are all daemon threads. 2.守护线程为用户线程服务->JVM的垃圾回收、内存管理等线程都是守护线程->还有就是在做数据库应用时候,使用的数据库连接池,连接池本身也包含着很多后台线程,监控连接个数、超时时间、状态等->User Thread已经全部退出运行了->只剩下Daemon Thread存在了->虚拟机退出->因为没有被守护的用户线程了->守护线程存在就无意义了-> 3.thread.setDaemon(true)必须在thread.start()之前设置->否则会跑出一个IllegalThreadStateException异常->你不能把正在运行的常规线程设置为守护线程 4.在Daemon线程中产生的新线程也是Daemon的-> 5.通常server shutdown的线程设置为守护线程->该首付线程负责shutdown所有的用户线程->在用户线程shutdown ok->jvm退出->shutdown的守护线程自然退出->不要把一些应用的业务放在守护线程做->否则当用户线程结束的时候,jvm就退出了->而此时可能守护线程的task还未执行完毕->
8.关于阻塞IO
线程阻塞->放弃CPU,暂停运行->只有等待导致阻塞的原因消除->或者被其他线程中断->则退出阻塞状态->并抛出InterruptedException.
线程阻塞原因:
1.Thread.sleep(long n)->线程放弃CPU->睡眠n毫秒,然后恢复运行->
2.线程执行一段同步代码->由于无法获得同步锁->阻塞->直到获得同步锁->恢复运行->
3.线程执行了一个对象的wait->进入阻塞->等待其他线程执行了该对象的notify()或notifyAll唤醒
4.线程执行io操作或远程通信->会因为等待相关的资源而进入阻塞状态->如System.in.read()->
远程通信,Client可能进入阻塞状态->
1.Socket#connect->阻塞->直到连接成功
2.Socket#read->没有足够的数据->阻塞->读到了足够的数据/输入流末尾/异常->才会返回或者异常中断-> read()->输入流中只需要一个字节就足够->read(byte[] buff)->只要输入流中的字节数目与buff数组的长度相同即足够->readLine->只要输入流中有一行字符串就足够(BufferedReader)
3.Socket#write->阻塞->直到输出了所有的数据或者出现异常->才返回或者异常中断
4.Socket#setSoLinger->设置关闭Socket延迟时间->Socket#close->进入阻塞->直到底层Socket发送完所有剩余数据或者到了SoLinger的超时时间->返回
Server也可能进入阻塞状态->
1.ServerSocket#accept->直到接收到了Client连接才返回
2.#read->如果输入流没有足够的数据->阻塞
3.#write->阻塞->直到输出了所有数据或出现异常->
->无论是Client还是Server->通过Socket输入输出流读写数据->都可能进入阻塞状态->阻塞IO->如果执行输入输出操作时->不发生阻塞->非阻塞IO
posted on 2013-08-06 12:40
landon 阅读(1852)
评论(1) 编辑 收藏 所属分类:
Program