并发编程之Thread

    Thread类是java中线程的定义,创建时可以设置线程要执行的代码,调用start方法会创建并执行真正的线程,通知管理线程的中断和线程的状态。

目录

1. 创建并执行一个简单的线程

2.sleep方法主动休眠

3.线程中断

4. sleep等待中的线程收到中断标记,会抛出InterruptedException异常,并清除中断标记

5. 线程同步join

6 线程两阶段终止线程中断示例


1. 创建并执行一个简单的线程

package org.example.concurrent;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

import java.util.concurrent.TimeUnit;

@Slf4j
public class ThreadTest {
    @Test
    public void test() {
        // 创建线程,入参为线程要执行的代码,这里打印一行日志
        Thread thread = new Thread(() -> log.debug("Hello world!"));

        // 创建并执行线程
        thread.start();
        sleep(10L);
    }


    @SneakyThrows
    private void sleep(long delay) {
        TimeUnit.MILLISECONDS.sleep(delay);
    }
}

2.sleep方法主动休眠

    Thread的静态方法sleep可以让线程主动休眠,入参为休眠的指定时间

package org.example.concurrent;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

import java.util.concurrent.TimeUnit;

@Slf4j
public class ThreadTest {
    @Test
    public void test() {
        // 创建线程,入参为线程要执行的代码,这里打印一行日志
        Thread thread = new Thread(() -> {
            log.debug("start");
            sleep(1000L); // 休眠1秒
            log.debug("end");
        });

        // 创建并执行线程
        thread.start();
        sleep(2000L);
    }


    @SneakyThrows
    private void sleep(long delay) {
        TimeUnit.MILLISECONDS.sleep(delay);
    }
}

log日志end会比start晚1秒打印,打印结果如下:

21:27:30.627 [Thread-0] DEBUG org.example.concurrent.ThreadTest - start
21:27:31.644 [Thread-0] DEBUG org.example.concurrent.ThreadTest - end

3.线程中断

   Thread的interrupt方法用于设置线程中断标记。

   Thread的isInterrupted方法用于判断线程是否有中断标记

   Thread的静态方法interrupted返回当前线程是否有中断标记,并清除中断标记。

示例1: sInterrupted方法用于判断线程是否有中断标记

package org.example.concurrent;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

import java.util.concurrent.TimeUnit;

@Slf4j
public class ThreadTest {
    @Test
    public void test() {
        // 创建线程,入参为线程要执行的代码,这里打印一行日志
        Thread thread = new Thread(() -> {
            Thread currentThread = Thread.currentThread();
            while (!currentThread.isInterrupted()) {
                // 线程未中断这一直执行
            }
            log.debug("当前中断标记为:{}", currentThread.isInterrupted());
        }, "t1");

        // 创建并执行线程
        thread.start();
        sleep(10);

        // 中断线程
        thread.interrupt();

        sleep(1000);
    }

    @SneakyThrows
    private void sleep(long delay) {
        TimeUnit.MILLISECONDS.sleep(delay);
    }
}

执行结果:

21:40:33.816 [t1] DEBUG org.example.concurrent.ThreadTest - 开始sleep
21:40:33.833 [t1] DEBUG org.example.concurrent.ThreadTest - currentThread has been interrupted

示例2:静态方法interrupted返回当前线程是否有中断标记,并清除中断标记

package org.example.concurrent;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

import java.util.concurrent.TimeUnit;

@Slf4j
public class ThreadTest {
    @Test
    public void test() {
        Thread thread = new Thread(() -> {
            Thread currentThread = Thread.currentThread();
            while (true) {
                if (Thread.interrupted()) {
                    log.debug("检测到当前线程中断");
                    break;
                }
            }
            log.debug("中断标记:{}", currentThread.isInterrupted());
        }, "t1");

        // 创建并执行线程
        thread.start();
        sleep(10);

        // 中断线程
        thread.interrupt();
        sleep(1000L);
    }

    @SneakyThrows
    private void sleep(long delay) {
        TimeUnit.MILLISECONDS.sleep(delay);
    }
}

执行结果:

21:48:37.217 [t1] DEBUG org.example.concurrent.ThreadTest - 检测到当前线程中断
21:48:37.221 [t1] DEBUG org.example.concurrent.ThreadTest - 中断标记:false

4. sleep等待中的线程收到中断标记,会抛出InterruptedException异常,并清除中断标记

除了sleep,join,wait收到中断标记,都会抛出InterruptedException异常,并清除中断标记。

package org.example.concurrent;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

import java.util.concurrent.TimeUnit;

@Slf4j
public class ThreadTest {
    @Test
    public void test() {
        Thread thread = new Thread(() -> {
            log.debug("t1开始睡眠");
            try {
                Thread.sleep(1000L);
            } catch (InterruptedException e) {
                log.debug("sleep抛出InterruptedException异常,当前线程的中断标记为:{}", Thread.currentThread().isInterrupted());
            }
        }, "t1");

        thread.start();
        sleep(10L);
        thread.interrupt(); //中断线程
        sleep(1000L);
    }

    @SneakyThrows
    private void sleep(long delay) {
        TimeUnit.MILLISECONDS.sleep(delay);
    }
}

5. 线程同步join

    Thread的join方法用于线程同步,即当前线程等待指定线程执行完毕,也可以设置最大等待时间,当前线程等待超过最大等待时间后,会继续往下执行:

package org.example.concurrent;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

import java.util.concurrent.TimeUnit;

@Slf4j
public class ThreadTest {
    @Test
    public void test() throws InterruptedException {
        Thread t1 = new Thread(() -> {
            log.debug("t1开始执行");
            sleep(1000L);
            log.debug("t1执行完毕");
        }, "t1");

        t1.start();

        log.debug("开始执行t1.join");
        t1.join();
        log.debug("t1.join已经返回");
    }

    @SneakyThrows
    private void sleep(long delay) {
        TimeUnit.MILLISECONDS.sleep(delay);
    }
}

执行过程中,在线程t1执行完毕后,t1.join才会返回,主线程继续执行,执行结果如下:

22:15:10.527 [t1] DEBUG org.example.concurrent.ThreadTest - t1开始执行
22:15:10.527 [main] DEBUG org.example.concurrent.ThreadTest - 开始执行t1.join
22:15:11.533 [t1] DEBUG org.example.concurrent.ThreadTest - t1执行完毕
22:15:11.534 [main] DEBUG org.example.concurrent.ThreadTest - t1.join已经返回

6 线程两阶段终止线程中断示例

所谓两阶段终止是指:

  1. 主动调用isInterrupted检查是否被中断,如果被中断则进入中断处理
  2. 如果使用了sleep、join、wait等操作,需要catch中断异常,并进入中断处理
package org.example.concurrent;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

import java.util.concurrent.TimeUnit;

@Slf4j
public class ThreadTest {
    @Test
    public void test() throws InterruptedException {
        Thread t1 = new Thread(this::monitor, "t1");

        t1.start();
        sleep(10L);
        t1.interrupt();
        t1.join();
    }

    private void monitor() {
        Thread currentThread = Thread.currentThread();

        // 1.while条件为当前线程未中断,则一直执行
        while (!currentThread.isInterrupted()) {
            try {
                log.debug("monitor 处理");
                Thread.sleep(5L);
            } catch (InterruptedException e) {
                // sleep抛出异常后,会清除中断标记,重新设置中断标记,也可以直接break
                currentThread.interrupt();
            }
        }

        log.debug("中断处理");
    }

    @SneakyThrows
    private void sleep(long delay) {
        TimeUnit.MILLISECONDS.sleep(delay);
    }
}

执行结果:

22:25:43.634 [t1] DEBUG org.example.concurrent.ThreadTest - monitor 处理
22:25:43.644 [t1] DEBUG org.example.concurrent.ThreadTest - monitor 处理
22:25:43.650 [t1] DEBUG org.example.concurrent.ThreadTest - monitor 处理
22:25:43.652 [t1] DEBUG org.example.concurrent.ThreadTest - 中断处理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值