Java多线程是一个运用很广的技术,特别是在分布式系统应用中。必须要好好学习,掌握它。
学习Java用的是《Java核心技术》第九版,下面,就跟着书里的介绍顺序,记录Java多线程吧。
多线程程序,是指可以同时运行一个以上线程的程序。
多线程和多进程的区别:本质区别在于每个进程拥有自己的一整套变量,而线程则共享数据。共享变量使线程之间的通信比进程之间的通信更有效、更容易。此外,在有些操作系统中,与进程相比较,线程更“轻量级”,创建、撤销一个线程比启动新进程的开销要小得多。
一、启动一个线程
下面是一个单独得线程中执行一个任务得简单过程:
1)将任务代码写到实现了 Runnable 接口的类的 run 方法中。这个接口,只有一个方法:
public interface Runnable{
void run();
}可以如下实现一个类:
public class MyRunnable implements Runnable{
public void run(){
//....
}
}
2)创建一个类对象
Runnable r = new MyRunnable();
3)由 Runnable 创建一个 Thread 对象
Thread t = new Thread(r);
4)启动线程
t.start二、中断线程
当线程的 run 方法执行方法体中最后一条语句后,并经由执行 return 语句返回时,或者出现了在方法中没有捕获的异常时,线程将终止。Java早期版本中,还有一个 stop 方法,其他线程可以调用它终止线程。但是,这个方法现在已经弃用了。
没有可以强制线程终止的方法,然而,interrupt 方法可以用来请求终止线程。
当对一个线程调用 interrupt 方法时,线程的 中断状态 将被置位(这是每一个线程都具有的 boolean 标志)。每个线程都应该时不时检查这个标志,以判断线程是否中断。
要想知道 中断状态是否被置位:首先,调用静态的 Thread.currentThread 方法获得当前线程,然后调用 isInterrupted 方法:
while(!Thread.currentThread().isInterrupted() && others){
//do ...
}
当在一个被阻塞的线程(调用sleep 或者wait)上调用 interrupt 方法时,阻塞调用将会被Interrupted 异常中断。
一个被中断的线程并不意味着该线程终止。中断一个线程不过时引起注意。被中断的线程可以决定如何响应中断。某些线程很重要,以至于应该处理完异常后,继续执行,而不理会中断。但是,更普遍的情况是,线程将简单地将中断作为一个终止的请求。这种线程的 run 方法具有如下形式:
public void run(){
try{
...
while(!Thread.currentThread().isInterrupted() && others){
// do ...
}
catch(InerruptedException e){
// Thread was interrupted during sleep or wait
}
finally{
clean up,if required
}
}如果在每次工作迭代之后都调用 sleep 方法(或者其他可中断方法),isInterrupted 检测既没有必要也没有用处(因为该线程已经sleep了)。
如果在 中断状态 被置位时,调用 sleep 方法,它不会休眠。相反,它将清楚这一状态,并抛出InterruptedException。因此,如果某循环调用sleep,不会检查中断状态。相反,要如下所示捕获InterruptedException异常:
public void run(){
try{
...
while(more work to do){
// do more work
Thread.sleep(delay);
}
}
catch(InterruptedException e){
// thread was interrupted during sleep
}
finally{
clean up, if required
}
}注意:有两个非常类似的方法,interrupt 和 isInterruptedd。interrupt 方法是一个静态方法,它检测当前的线程是否被中断。而且,调用 interrupt 方法会清除该线程的中断状态。另一方面,isInterrupted 方法是一个实例方法,可用来检验是否有线程被中断。调用这个方法不会改变中断状态。
————————————
其中,很多代码中,InterruptedException异常被抑制在很低的层次上,像这样:
void mySubTask(){
... try{sleep(delay);} catch(InterruptedException e){}// <---- ...
}不要这样做。如果不认为在catch子句中做这一处理有什么好处的话,可以采用下面两种合理的方式:
(1)在 catch 子句中调用Thread.currentThread().interrupt() 来设置中断状态。于是调用者可以对其进行 检测。
void mySubTask(){
...
try{sleep(delay)}
catch(InterruptedException e){Thread.currentThread().interrupt();}
}
(2)或者,更好的选择是,用 throws InterruptedException 标记方法,不采用 try 语句块捕捉异常。于是,调用者可以捕获这一异常。
void mySubTask() throws InterruptedException{
...
sleep(delay);
...
}三、线程状态
线程可以有如下6种状态:
New 新创建
Runnable 可运行
Blocked 被阻塞
Waiting 等待
Timed waiting 计时等待
Terminated 被终止
要确定一个线程的当前状态,可调用 getState 方法。
10万+

被折叠的 条评论
为什么被折叠?



