Java并发编程的艺术学习笔记(四)

Java并发编程基础(一)

1. Java线程的状态

1.1 New

初始状态,创建线程但还没有调用start()方法。

1.2 Runnable

运行状态,Java线程的运行状态包括运行和就绪两种状态。

1.3 Block

阻塞状态,线程获取锁失败时进入阻塞状态。

1.4 Waiting

等待状态,进入等待状态的线程要需要等待其他线程的一些特定动作,如通知或中断。

1.5 Terminated

终止状态,表示退出当前线程。

2. Java线程状态变迁图

注意:阻塞状态是Java线程阻塞于synchronize修饰的同步方法或同步块(获取锁失败时),但阻塞在Java.Concurent包中Lock接口的线程状态却是等待状态

3. 中断

3.1 理解中断

中断可以认为是线程的一个boolean类型的标志位属性,当一个线程(本线程或其他线程均可)调用方法Thread.interrupt()时该boolean值被设置为true,表示线程将被中断,即一个运行中的线程可被本线程或另一个线程中断。

3.2 中断的相关方法

方法调用主体作用
public void interrupt()Thread类实例对象使被中断线程的中断标志位设置为true
public boolean isInterrupted()Thread类实例对象判断线程的中断状态
public static boolean interrupted()Thread类静态方法对当前线程的中断标志位进行复位

3.3 线程的suspend()、resume()、stop()方法(均已过期)

●suspend():暂停线程。调用此方法后,线程虽进入睡眠状态,但不会释放占有的资源(比如锁),这样可能导致死锁的发生。

●resume():恢复处于睡眠状态的线程。

●stop():终结线程。该方法不保证线程在终结后能正常的释放线程资源,通常情况下不给予线程释放资源的机会,这将导致线程处于不确定的工作状态下。


注意:正因为suspend()、resume()、stop()自带的缺陷,所以这些方法才被标注为已过期。线程的暂停和恢复功能可通过等待/通知制来实现。

3.4 中断的使用

中断线程可分为三种类型:(1)中断非阻塞线程 (2)中断阻塞线程 (3)不可中断线程


●(1)中断非阻塞线程。中断方式有采用共享变量中断、采用中断机制。


  • ●采用共享变量中断:利用一个自定义volatile boolean变量充当线程中断的标志位。
        public class Test1 {

            public volatile boolean on = false; //volatile变量修改后其他线程立即可见
        
            public static void main(String[] args) {
                Thread thread = new Thread( new Runnable() {
                    @Override
                    public void run() {
                        while(!on) { //当前线程没有被中断时
                                     //执行正常的任务
                                    //若当前线程被中断,即on被设置为true时,就会跳出这个循环
                        }
        
                        //执行到这时,说明线程已被中断,可以在这进行线程中断后资源的释放操作。
        
                    }
                } );
            }
}  
复制代码

  • ●采用中断机制:通过调用线程的中断方法实现中断。

  • Thread thread = new Thread( new Runnable() {
    
              @Override
              public void run() {
                  while(!Thread.currentThread().isInterrupted()) {
                      //当前线程没有被中断时
                      //执行正常的任务
                      //若当前线程被中断,即有线程调用了Thread.interrupt()方法时,就会跳出这个循环
                  }
    
                  //执行到这时,说明线程已被中断,可以在这进行线程中断后资源的释放操作。
              }
          });
    复制代码
  • 小结:

  • ●要实现非阻塞线程中断,程序要能够检测到中断标志位的变化(如通过while循环判断),否则即使中断标志位为true,也无法实现中断。

  • ●上述两种中断非阻塞线程的方式在本质上是一致的,即都是通过感应中断标志位的变化来实现中断的逻辑。

  • ●上述两种方式是安全的,因为线程在中断后有机会去清理资源。


●(2)中断阻塞线程。当线程调用Object.wait()、Thread.sleep()等方法时,线程处于阻塞状态。此时调用线程的中断方法会抛出InterruptedException异常来实现线程的中断。需要注意的是,InterruptedException异常抛出后中断标志位被设置为false,即isInterruped()方法的返回值为false,此时我们需要调用Thread.interrupt()方法再次把中断标志位设置为true,否则线程又将继续执行下去。 这里分享一点个人心得:有些资料会把线程的等待状态称为等待阻塞,线程的阻塞则称为同步阻塞。按照这种思路,线程调用Object.wait()方法时进入的状态为等待阻塞状态,也是线程的等待状态,这里容易混乱。

 Thread thread = new Thread( new Runnable() {

            @Override
            public void run() {
                while(!Thread.currentThread().isInterrupted()) {
                    try {
                        Thread.currentThread().sleep(5000);//当线程执行到这而又被中断时,这里将抛出InterruptedException异常。
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();//这里需要把中断标志位再次设置为true,否则无法跳出循环从而实先中断。
                        e.printStackTrace();
                    }
                }

                //执行到这时,说明线程已被中断,可以在这进行线程中断后资源的释放操作。
            }
        });
复制代码

●(3)不可中断线程。线程在使用synchronize同步块获取锁后是无法被中断的。

转载于:https://juejin.im/post/5ce155f9e51d4510b25a3ecd

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值