线程阻塞详解(定义原因及阻塞方法)

线程阻塞详解(定义原因及阻塞方法)-mikechen

线程阻塞经常在Java面试被问到,比如:什么是线程阻塞?线程阻塞方法等问题,下面我就来详解线程阻塞@mikechen

什么是线程阻塞?

线程阻塞是指一个线程被挂起,暂时停止执行,直到某个条件满足或等待的时间到达后才会继续执行。

 

为什么会出现线程阻塞?

线程阻塞通常是因为某种等待条件没有得到满足,比如等待 I/O 操作完成、等待其他线程释放锁或信号量、等待某个事件的发生等。

线程阻塞通常是由于以下原因引起:

1.等待 I/O 操作

当线程需要进行 I/O 操作(如读写磁盘或网络通信)时,线程会被阻塞,直到 I/O 操作完成或者出现错误。

2.同步等待

当线程需要等待其他线程释放某个共享资源(如锁或信号量)时,线程会被阻塞,直到获取该资源并完成操作。

3.睡眠等待

当线程需要等待一段时间后再执行某个操作时,可以使用睡眠等待的方式,这时线程会被阻塞,直到等待时间结束。

4.等待信号

线程有时需要等待某个信号的到来,如 Unix 系统的信号机制,这时线程会被阻塞,直到信号到达并被处理。

 

线程阻塞的方法

Java 中常见的线程阻塞方法有以下几种:

1.sleep()方法

该方法会让线程睡眠一段时间,可以指定毫秒或纳秒的时间,使得线程暂停执行,等待指定时间后再被唤醒。

public class SleepDemo {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            System.out.println("Thread started.");
            try {
                Thread.sleep(5000); // 线程睡眠 5 秒钟
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Thread finished.");
        });
        thread.start();
        try {
            thread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

 

2.join()方法

该方法会使调用线程等待目标线程执行完毕,直到目标线程终止才会返回。

public class JoinDemo {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            System.out.println("Thread started.");
            try {
                Thread.sleep(5000); // 线程睡眠 5 秒钟
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Thread finished.");
        });
        thread.start();
        try {
            thread.join(); // 等待线程执行完毕
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Main thread finished.");
    }
}

 

3.wait() 和 notify()

这是 Java 中线程间同步的两个基本方法,使用 wait() 方法可以使当前线程进入等待状态,直到其他线程调用 notify() 或 notifyAll() 方法将其唤醒。

public class WaitNotifyDemo {
    public static void main(String[] args) {
        Object lock = new Object();
        Thread thread1 = new Thread(() -> {
            synchronized (lock) {
                System.out.println("Thread 1 started.");
                try {
                    lock.wait(); // 线程 1 进入等待状态
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Thread 1 finished.");
            }
        });
        Thread thread2 = new Thread(() -> {
            synchronized (lock) {
                System.out.println("Thread 2 started.");
                lock.notify(); // 唤醒线程 1
                System.out.println("Thread 2 finished.");
            }
        });
        thread1.start();
        thread2.start();
        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

 

4.I/O 阻塞方法

Java 中的 I/O 操作是阻塞式的,当输入或输出操作无法立即完成时,线程会被阻塞,直到 I/O 操作完成。

 

5.Lock 和 Condition方法

Java 中的 Lock 和 Condition 接口提供了更灵活的线程同步方式,可以使用 lock() 和 unlock() 方法控制线程的互斥访问,使用 Condition 接口的 await() 和 signal() 方法实现线程间协作。

以上就是线程阻塞的详解,更多多线程内容,请查看:Java多线程编程详解(看这篇就足够了)

陈睿mikechen

10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。

关注「mikechen」公众号,获取更多技术干货!

后台回复面试即可获取《史上最全阿里Java面试题总结》,后台回复架构,即可获取《阿里架构师进阶专题全部合集

评论交流
    说说你的看法