Java多线程

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 方法。





评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值