Java多线程

来源:互联网 发布:甲醇产业链网络协会 编辑:程序博客网 时间:2024/06/14 17:19

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 ...}


但是,如果线程被阻塞,就无法检查 中断状态 。这是产生 InterruptedException 异常 的地方。

当在一个被阻塞的线程(调用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 方法。





原创粉丝点击