【Java 并发编程】线程的基本使用(持续更新优化)

目录

一、Thread

1.1 构造方法

1.2 核心属性

二、线程的操作方法

2.1 启动线程

2.2 线程中断机制

2.2.1 线程中断机制

2.2.2 中断线程的常见方式

2.2.2.1 使用自定义的标志位结合 volatile 实现

2.2.2.2 通过 AtomiucBoolean 进行中断

2.2.2.3 interrupted

2.2.2.4 isInterrupted

2.2.4 线程中断的注意事项

2.3 线程等待

2.4 获取当前线程引用

2.5 线程休眠暂停执行

2.6 线程让步

三、线程的进阶使用方式

3.1 线程中断 LockSupport

3.1.1 线程等待和唤醒的方法

3.1.2 Object的线程等待唤醒机制

3.1.3 Condition的线程等待唤醒机制

3.1.4 LockSupport 的线程阻塞和唤醒

3.1.5 LockSupport 方法介绍


一、Thread

Thread 类是 JVM 用来管理线程的一个类,换句话说,每个线程都有一个唯一的 Thread 对象与之关联。Thread 类的对象就是用来描述一个线程执行流的,JVM 会将这些 Thread 对象组织起来,用于线程调度,线程管理。

1.1 构造方法

Thread t1 = new Thread();
Thread t2 = new Thread(new MyRunnable());
Thread t3 = new Thread("这是我的名字");
Thread t4 = new Thread(new MyRunnable(), "这是我的名字");

 name参数,是给线程起了一个名字。这里的名字,不影响程序执行,只是方便咱们在调试的时候,快速找到咱们关心的线程。

1.2 核心属性

  • ID 是线程的唯一标识,不同线程不会重复
  • 名称是各种调试工具用到
  • 状态表示线程当前所处的一个情况,下面我们会进一步说明
  • 优先级高的线程理论上来说更容易被调度到
  • 关于后台线程,需要记住一点:JVM会在一个进程的所有非后台线程结束后,才会结束运行。也就是说前台线程会阻止java进程结束,后台进程不会阻止进程的结束。创建的线程默认是前台的,可以通过setDaemon设置为后台的。
  • 是否存活,即简单的理解,为 run 方法是否运行结束了
  • 线程的中断问题,下面我们进一步说明
public static void main(String[] args) {
    Thread thread = new Thread(() -> {
        for (int i = 0; i < 10; i++) {
            try {
                System.out.println(Thread.currentThread().getName() + ": 我还活着");
                        Thread.sleep(1 * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(Thread.currentThread().getName() + ": 我即将死去");
    });
    System.out.println(Thread.currentThread().getName() + ": ID: " + thread.getId());
    System.out.println(Thread.currentThread().getName() + ": 名称: " + thread.getName());
    System.out.println(Thread.currentThread().getName() + ": 状态: " + thread.getState());
    System.out.println(Thread.currentThread().getName() + ": 优先级: " + thread.getPriority());System.out.println(Thread.currentThread().getName() + ": 后台线程: " + thread.isDaemon());
    System.out.println(Thread.currentThread().getName() + ": 活着: " + thread.isAlive());
    System.out.println(Thread.currentThread().getName() + ": 被中断: " + thread.isInterrupted());
    thread.start();
    while (thread.isAlive()) {}
    System.out.println(Thread.currentThread().getName() + ": 状态: " + thread.getState());
}

二、线程的操作方法

2.1 启动线程

在系统中真正创建出线程需要如下步骤,而系统 API start 方法会在系统内核将对应任务进行创建:

  1. 创建 PCB 进程管理块
  1. 把 PCB 加入到对应链表

启动线程的步骤如下:

  1. 重写 run 方法:确定线程的业务逻辑
  2. 调用 start 方法:让线程独立执行

2.2 线程中断机制

2.2.1 线程中断机制

一个线程不应该由其他线程来强制中断或停止,而是应该由线程自己自行停止,自己来决定自己的命运。所以Thread.stop、Thread.suspend、Thread.resume都已经被废弃了。

线程中断机制:Java中没有办法立即停止一条线程,然后停止线程却显得尤为重要,如取消一个耗时操作。因此,Java中提供了一种用于停止线程的协商机制(中断),也即中断表示协商机制。Java并没有给中断增加任何语法,中断的过程完全需要自己实现。

若要中断一个线程,你需要手动调用该线程的 interrupt 语法,该方法也仅仅是将线程对象的中断标识设置为 true,接着你需要自己写代码不断检查当前的线程的标识位,如果为 true ,表示别的线程请求这条线程中断,此时究竟该做什么需要程序员写代码实现。

每个线程对象中都有一个中断标识位,用于表示线程是否被中断。该标识位为 true 表示中断,为 false 表示未中断。通过调用线程对象的 interrupt 方法将该线程的标识位设置为 true,可以在别的线程中调用,也可以在自己的线程中调用。

2.2.2 中断线程的常见方式

  1. 通过共享的标记位来进行线程间通信
  2. volatile 修饰的变量保证内存可见性
  3. AtomicBoolean 原子类保证原子性及内存可见性
  4. 通过 interrupt 方法进行线程间通知:仅仅设置现成的中断状态为 true,发起一个协商而不会立刻停止线程。
  5. interrupted:判断线程是否被中断(返回当前线程的中断状态)并清除当前中断状态(设置为false)
  6. 有可能两次调用的结果是不同的
  7. isInterrupted:判断当前线程是否被中断
2.2.2.1 使用自定义的标志位结合 volatile 实现
public class InterruptDemo {
    // 保证内存可见性
    static volatile boolean isStop = false;

    public static void main(String[] args) {
        new Thread(()->{
            while(true){
                if(isStop){
                    System.out.println(Thread.currentThread().getName()+"\t"+"stop");
                    break;
                }
                System.out.println("Hello");
            }
        },"t1").start();
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        new Thread(()->{
            isStop = true;
        },"t2").start();
    }
}

注意事项:

  1. Lambda表达式能够访问外面的局部变量的前提是该变量被final或者是‘实际final(代码中未对该变量做出修改)’。这样设计的目的是因为“变量捕获”。避免:如果外面的代码要对这个变量进行修改,就会出现一个情况,外面的变量变了里面的没变,代码更容易出现歧视。
  1. isQuit从成员变量改为局部变量,导致程序无法正常运行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

敖云岚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值