多线程基础(四)

一、等待线程-join()

在我们平常写代码的 时候会遇到需要等待一个线程执行完毕的时候,再执行下一个线程,然而我们之前学过的sleep具有以下特性:

  • 当前线程停止运行指定的毫秒数。时间一到,线程自动进入"就绪状态",等待 CPU 调度。
  • 它不释放锁。如果当前线程持有了某个对象的同步锁(synchronized),在 sleep 期间,其他线程依然无法获取该锁。

所以我们不可能精准预测每一个线程执行所耗费的时间,为了避免这个问题,我们通常用join()函数。

复制代码
public class demo3 {
    public static void main(String[] args) throws InterruptedException {
        Runnable target=()->{
            for (int i = 0; i < 10; i++) {
                try {
                    System.out.println(Thread.currentThread().getName() + " 我正在工作" );
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }

            }
            System.out.println(Thread.currentThread().getName() + " 工作结束");
        };
        Thread t1=new Thread(target,"张三");
        Thread t2=new Thread(target,"李四");
        System.out.println("先让李四开始工作");
     t2.start();
        t2.join();
        System.out.println("李四工作结束了,让张三开始工作");
        t1.start();
        t1.join();

    }


}

join函数的特性:

复制代码
Thread t = new Thread(() -> { /* 任务 */ });
t.start();
t.join(); // 当前线程在这里卡住,直到 t 运行结束

当前线程阻塞,直到目标线程 t 执行完毕(终止)。

它底层其实也是利用了 wait() 机制,因此会释放锁。如果在 synchronized 块中调用 join(),当前线程会释放锁,允许其他线程进入临界区,直到目标线程结束或被中断。

常用于:主线程需要等待子线程计算结果后才能继续(例如:先下载数据,再处理数据)。

复制代码
join在main中就是主线程等待引用join的线程运行结束,
如果是在t2中使用t1.join就是t2等待t1结束

上面使用的join都是没有参数的版本,没有参数就是,等待的线程不结束就会一直等,这个等待会很容易出bug就像租界女友的男主(忘了叫什么了),一直舔着水原千鹤,但她是租界女友而且也不会喜欢他,这时候bug就出现了,男主就算等到老死也等不到水原千鹤喜欢他(看一部劝退)

这个时候我们就该引入带参数的join了

复制代码
public class demo4 {
    public static void main(String[] args) throws InterruptedException {
        Thread thread1=new Thread(()->{
            System.out.println("Hello from thread");
        });
        Thread thread2=new Thread(()->{
            System.out.println("Hello from thread");
            try {
                thread1.join();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
        thread1.start();
        thread1.join();
        thread2.start();

    }
}

public class demo4 {
    public static void main(String[] args) throws InterruptedException {
        Thread thread1=new Thread(()->{
            System.out.println("Hello from thread");
        });
        Thread thread2=new Thread(()->{
            System.out.println("Hello from thread");
            try {
                thread1.join(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
        thread1.start();
        thread1.join(1000);
        thread2.start();

    }
}

第三个没怎么用过,我这边就不提了。

复制代码
public static Thread currentThread();

咱们之前提到过这个方法,用来获取当前线程的引用

复制代码
public class demo5 {
    public static void main(String[] args) {
        Thread t=Thread.currentThread();
        System.out.println(t.getName());
    }
}

再提一嘴sleep()方法:

sleep会让调用的线程阻塞等待,是有一定的时间的

线程执行sleep的时候就会使这个线程不参与cpu的调度,从而把cpu的资源让出来,给别人用。

这种操作被称为"放权",再某些开发的过程中发现cpu占用过高就可以通过sleep来进行改善。

线程状态

线程共有六种状态

  • new
  • runnable
  • blocked
  • waiting
  • timed_waiting
  • terminated

进程状态:

  • 就绪
  • 阻塞

就绪:正在cpu上执行或者随时可以去cpu上执行

阻塞:暂时不参与cpu执行

线程内的状态是一个枚举类型Thread.State

复制代码
public class demo6 {
    public static void main(String[] args) {
        for (Thread.State state:Thread.State.values()){
            System.out.println(state);
        }
    }
}

运行结果为:

复制代码
NEW
RUNNABLE
BLOCKED
WAITING
TIMED_WAITING
TERMINATED

new:当前Thread对象虽然有了,但是内核的线程还没有(这个时候并没有调用start)

runnable:就绪态,正在cpu上执行或者随时可以去cpu上执行

以下三个是阻塞态:

  • blocked,因为锁竞争而近期的阻塞
  • waiting,没有超时等待
  • timed_waiting,有超时等待或者join带参数版本
相关推荐
Yang-Never2 小时前
ADB ->adb shell perfetto 抓取 trace 指令
android·开发语言·adb·android studio
小鸡吃米…2 小时前
Python 网络爬虫 —— 环境设置
开发语言·爬虫·python
Java成神之路-2 小时前
深入 JVM:G1 垃圾回收器原理与实现细节
java·jvm
add45a2 小时前
C++中的观察者模式
开发语言·c++·算法
该怎么办呢2 小时前
Source/Core/Event.js
开发语言·javascript·ecmascript·cesium
似水明俊德2 小时前
04-C#.Net-委托和事件-面试题
java·开发语言·面试·c#·.net
johnrui2 小时前
集合与树形结构
开发语言·windows
好家伙VCC2 小时前
# 发散创新:用 Rust构建高性能游戏日系统,从零实现事件驱动架构 在现代游戏开发中,**性能与可扩展性**是核心命题。传统基于
java·python·游戏·架构·rust