Java Thread 线程

发布于 2024-04-09 03:54:27 字数 4293 浏览 17 评论 0

Thread 常用方法

join()

等待线程结束

void interrupt()

中断线程。如果当前线程正在运行,则只是设置中断标记,不会中断;如果当前线程处于非运行状态,则会抛出 InterruptedException 异常。

boolean isInterrupted()

获取线程中断状态。

public boolean isInterrupted() {
    return isInterrupted(false);
}

boolean interrupted()

获取线程中断状态。如果当前已被中断,清除中断标记。

public static boolean interrupted() {
    return currentThread().isInterrupted(true);
}

其中 isInterrupted 含参数的方法定义如下

/**
* Tests if some Thread has been interrupted.  The interrupted state
* is reset or not based on the value of ClearInterrupted that is
* passed.
*/
private native boolean isInterrupted(boolean ClearInterrupted);

线程上下文

线程上下文切换的时机:当前线程 CPU 时间片使用完毕,或当前线程被其他线程中断。

死锁

死锁的四个条件

  • 互斥。即线程持有的资源是排他的,不是共享的。
  • 请求并持有。一个线程持有资源 A,但是请求资源 B,但是资源 B 被其他线程占用,因此这个线程阻塞,但是它也不释放资源 A。
  • 不可剥夺。一个线程获取到的资源不会被别的线程强行抢走。
  • 环路等待。必然存在一个环形的资源等待链。R1->R2->...->Rn->R1。

死锁代码:

public class DeadLock {
    private static Object resourceA=new Object();
    private static Object resourceB=new Object();
    public static void main(String[] args) {
        Thread thread1 = new Thread(() -> {
            synchronized (resourceA) {
                System.out.println(Thread.currentThread() + "get resourceA");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread() + "wait to get resourceB");
                synchronized (resourceB) {
                    System.out.println(Thread.currentThread() + "get resourceB");
                }
            }
        });

        Thread thread2 = new Thread(() -> {
            synchronized (resourceB) {
                System.out.println(Thread.currentThread() + "get resourceB");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread() + "wait to get resourceA");
                synchronized (resourceA) {
                    System.out.println(Thread.currentThread() + "get resourceA");
                }
            }
        });

        thread1.start();
        thread2.start();
    }
}
Thread[Thread-0,5,main]get resourceA
Thread[Thread-1,5,main]get resourceB
Thread[Thread-0,5,main]wait to get resourceB
Thread[Thread-1,5,main]wait to get resourceA

线程 1 持有 resourceA,并请求 resourceB;线程 2 持有 resourceB,并请求 resourceA。造成了死锁。

避免死锁:将线程 2 获取资源的顺序改为和线程 1 获取资源的顺序保持一致。

Thread thread2 = new Thread(() -> {
    synchronized (resourceA) {
        System.out.println(Thread.currentThread() + "get resourceA");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread() + "wait to get resourceB");
        synchronized (resourceB) {
            System.out.println(Thread.currentThread() + "get resourceB");
        }
    }
});
Thread[Thread-0,5,main]wait to get resourceB
Thread[Thread-0,5,main]get resourceB
Thread[Thread-1,5,main]get resourceA
Thread[Thread-1,5,main]wait to get resourceB
Thread[Thread-1,5,main]get resourceB

由于资源的有序分配,当线程 1 和线程 2 同时执行到 synchronized (resourceA) 时,只会有一个线程拿到资源 A,假设线程 1 拿到,那么线程 2 会因为抢不到资源 A 而被阻塞。

于是,线程 1 能够顺利继续获取资源 B,使用完之后,释放资源 A 和资源 B。线程 2 接着重复线程 1 的操作。

守护线程与用户线程

线程可以使用 setDaemon(true) 方法设置为守护进程。

子线程的生命周期不受父线程影响。

当最后一个非守护线程结束时,JVM 会正常退出。只要有一个用户线程没结束,JVM 不会退出。

总结:非守护线程不会影响 JVM 的退出逻辑

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

娇妻

暂无简介

0 文章
0 评论
24 人气
更多

推荐作者

qq_E2Iff7

文章 0 评论 0

Archangel

文章 0 评论 0

freedog

文章 0 评论 0

Hunk

文章 0 评论 0

18819270189

文章 0 评论 0

wenkai

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文