Java并发 基础 二

时间:2021-10-15 08:05:58

1 、线程中断:

线程中断是一种重要的线程协作机制。线程中断并不会让线程退出,只是给线程发送一个通知,线程执行过程会检测到这个通知,然后可以自定义做出动作,比如退出,但也并不是都是退出。

线程中有三个有关中断的方法:

public void  interrupt()  中断线程
public booklean  isInterrupted() 判断是否被中断,不清除当前中断状态
public static  boolean interrupt() 判断是否被中断,并清除当前中断状态。
public class ThreadInterrupt {

    public static void main(String args[]) throws InterruptedException {
        Thread t1 = new Thread() {
            public void run() {

                while (true) {

                    if(Thread.currentThread().isInterrupted()){ //1 在中断处理中并未执行退出
                                                                // 2 此方法并未清除中断标志位,因此还会被检测到
                        System.out.println("线程第一次检测到中断,并不退出");

                    }
                    System.out.println("线程执行过程中 ");

                    if(Thread.currentThread().isInterrupted()){
                        System.out.println("线程再次检测到中断,然后退出");
                        break;
                    }

                    System.out.println("线程执行过程中 ");
                    Thread.yield();
                }

            }

        };

        t1.start();
        Thread.sleep(3000);
        t1.interrupt();

    }
}

Thead.sleep() 方法会让当前线程休眠若干时间,会抛出一个InterruptedException 中断异常。 不是运行时异常,程序必须捕获它。,当线程在sleep休眠时,如果被中断,这个异常就会产生。

Thread.sleep 方法由于中断而抛出异常,此时,它会清除中断标记,如果不加处理,那么在下一次循环开始时,就无法捕获这个中断,故在异常处理中,再次设置中断标记位。

2、等待 wait通知 notify

为了支持多线程之间的协作,jdk提供了两个非常重要的接口:wait 和notify方法。这两个方法在Object类中定义,这意味着任何对象都可以调用这两个方法,但是 wait和notify不是随意调用的,它必须包含在对应的synchronized语句中。还有个地方需要注意,尽量不在Thread实例上调用wait和notify方法。无论是wait还是notify,都需要首先获得目标对象的一个监视器。

线程执行wait和notify的流程:

T1在执行object.wait方法之前首先获得object对象的监视器,执行之后,释放object的监视器,此时线程就会进入等待状态, 等待其他线程的唤醒。

T2 在notify调用前,也必须获得object的监视器,此时T1已经释放了这个监视器,因此T2可以顺利获得object的监视器。接着T2执行了notify方法尝试唤醒一个等待线程,这里是随机唤醒,假设唤醒了T1 。T1被唤醒后,要做的第一件事并不是执行后续的代码,而是尝试从新获得object的监视器,而这个监视器也正是t1在wait方法执行前所持有的那个。

object.wait 和thread.sleep 方法都可以让线程等待若干时间。除了wait可以被唤醒外,另外一个主要的区别就是wait 方法会释放目标对象的锁,而Thread.sleep方法不会释放任何资源。

3、挂起 suspend 继续执行 resume

在导致线程暂停的同时,并不会释放任何资源。此时其他任何线程想要访问被它暂用的锁时,都会被牵连。导致无法正常继续运行。直到resume操作,假设无resume的执行,或者resume已经提前调用过了,那么这个线程永远处于挂起状态了。

4、等待线程结束 join 谦让 yield

join有两个方法签名,无参数的join,表示无限期等待, 有参数join表示等待指定的时间。

在线程T1中调用 T2.join 表示等待T2线程调用完毕之后,才会调用继续调用线程T1。
(显然在本身的方法里,调用自身的join方法是没有意义的。)

yield 总是一个静态方法,一旦执行,它会使当前线程让出CPU,但要注意,让出CPU并不是表示当前线程不执行了。当前线程在让出CPU后,还会进行CPU资源的争夺。

5、守护线程

Daemon 是一种特殊的线程,它是系统的守护者,在后台默默地完成一些系统性的服务。 比如垃圾回收线程,JIT线程。 当一个Java应用内,只有守护线程时,Java虚拟机就会自然退出。

6、关于synchronized的用法:

指定加锁对象: 对给定对象加锁,进入同步代码前要获得给定对象的锁。
直接作用于实例方法: 相当于对当前实例加锁,进入同步代码前要获得当前实例的锁。
直接作用于静态方法:相当于对当前类加锁,进入同步代码前要获得当前类的锁。