Java多线程面试题【线程状态】【线程同步和线程通信】【多接口实现多线程】【volatile关键字】【ReentrantLock关键字】

本人详解
作者:王文峰,参加过 CSDN 2020年度博客之星,《Java王大师王天师》
公众号:JAVA开发王大师,专注于天道酬勤的 Java 开发问题
中国国学、传统文化和代码爱好者的程序人生,期待你的关注和支持!本人外号:神秘小峯 山峯
转载说明:务必注明来源(注明:作者:王文峰哦)

在这里插入图片描述

学习教程(传送门)

1、掌握 JAVA入门到进阶知识(持续写作中……
2、学会Oracle数据库用法(创作中……
3、手把手教你vbs脚本制作(完善中……
4、牛逼哄哄的 IDEA编程利器(编写中……
5、吐血整理的 面试技巧(更新中……

Java多线程面试题及示例

## 面试题

1. 请解释Java中的线程与进程的区别。

在Java中,线程是进程内的一个执行单元,它共享进程的资源(如内存空间、文件句柄等),而进程是操作系统分配资源的基本单位。线程相较于进程更加轻量级,因此线程的创建、切换和销毁的开销通常比进程小得多。

2. 请简述Java中实现多线程的几种方式。

Java中实现多线程主要有三种方式:

  1. 继承Thread类:通过创建一个新类继承Thread类并重写其run()方法来实现多线程。
  2. 实现Runnable接口:通过创建一个新类实现Runnable接口并重写其run()方法,然后将该类的对象作为参数传递给Thread类的构造方法来创建线程。
  3. 实现Callable和Future接口:使用Callable接口可以返回一个值或抛出异常,而Future接口用于获取Callable执行的结果。这种方式通常与ExecutorService结合使用。

3. 请解释Java中的线程状态以及它们之间的转换。

Java中的线程状态包括:

  • 新建(NEW):新创建了一个线程对象。
  • 就绪(RUNNABLE):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。
  • 运行(RUNNING):线程获取了CPU使用权,执行程序代码。
  • 阻塞(BLOCKED):阻塞状态是指线程因为某种原因放弃了CPU使用权,也即让出了CPU timeslice,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。
  • 等待(WAITING):线程在等待另一个线程执行一个(唤醒)动作。
  • 超时等待(TIMED_WAITING):和WAITING状态类似,不过它可以在指定的时间后自行返回的线程状态。
  • 终止(TERMINATED):线程已退出。

4. 请说明Java中的线程同步和线程通信。

线程同步:多个线程并发访问共享数据时,为保证数据的一致性和完整性,需要对共享数据进行同步控制。Java中常用的线程同步机制包括synchronized关键字和Lock接口。

线程通信:线程通信是指线程之间以某种方式来交换信息。在Java中,线程通信的主要方式是使用wait()和notify()/notifyAll()方法,这些方法只能在同步方法或同步代码块中使用。另外,还可以使用Condition接口来实现更灵活的线程通信。

示例

使用Runnable接口实现多线程

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("线程 " + Thread.currentThread().getName() + " 正在运行");
    }

    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();
        Thread thread1 = new Thread(myRunnable, "线程1");
        Thread thread2 = new Thread(myRunnable, "线程2");

        thread1.start();
        thread2.start();
    }
}

使用synchronized实现线程同步

public class SynchronizedExample {
    private Object lock = new Object();
    private int count = 0;

    public synchronized void increment() {
        count++;
    }

    public synchronized void decrement() {
        count--;
    }

    public synchronized int getCount() {
        return count;
    }

    // 示例用法
    public static void main(String[] args) {
        SynchronizedExample example = new SynchronizedExample();

        // 创建两个线程分别进行增加和减少操作
        Thread incrementThread = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                example.increment();
            }
        });

        Thread decrementThread = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                example.decrement();
            }
        });

        incrementThread.start();
        decrementThread.start();

        // 等待两个线程执行完毕
        try {
            incrementThread.join();
            decrementThread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("最终计数:" + example.getCount()); // 可能是0,也可能是其他值,取决于两个线程的执行顺序和速度
    }
}

5. 请解释volatile关键字在Java中的作用,并举例说明。

volatile关键字是Java提供的一种轻量级的同步机制,它主要用于确保变量在多线程之间的可见性。当一个变量被声明为volatile时,它会保证修改的值会立即被更新到主内存,当有其他线程需要读取时,它会去主内存中读取新值。但是需要注意的是,volatile并不能保证复合操作的原子性。

示例

public class VolatileExample {
    private volatile boolean flag = false;

    public void setFlag(boolean flag) {
        this.flag = flag;
    }

    public boolean isFlag() {
        return flag;
    }

    public static void main(String[] args) {
        final VolatileExample example = new VolatileExample();

        new Thread(() -> {
            System.out.println("线程1开始等待flag...");
            while (!example.isFlag()) {
                // 等待flag变为true
            }
            System.out.println("线程1结束等待,flag为true");
        }).start();

        try {
            // 让主线程暂停一段时间,模拟其他线程先运行的情况
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 在主线程中修改flag的值
        example.setFlag(true);
    }
}

在这个例子中,如果flag没有被声明为volatile,那么线程1可能永远都看不到flag变为true,因为它一直在读取自己线程的工作内存中的值。但是,由于flag被声明为volatile,线程1能够立即看到主内存中flag的变化。

6. 请解释Java中的wait()notify()/notifyAll()方法,并给出使用它们的示例。

wait()notify()/notifyAll()是Java中用于线程间通信的方法,它们必须在同步代码块或同步方法中使用,否则会抛出IllegalMonitorStateException

  • wait():使当前线程等待,直到其他线程调用此对象的notify()方法或notifyAll()方法。当前线程必须拥有此对象的监视器(即,它必须是当前正在执行同步代码块的线程)。
  • notify():唤醒在此对象监视器上等待的单个线程。
  • notifyAll():唤醒在此对象监视器上等待的所有线程。

示例

public class WaitNotifyExample {
    private int count = 0;

    public synchronized void increment() {
        while (count == 5) {
            try {
                wait(); // 等待,直到其他线程调用notify()或notifyAll()
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        count++;
        System.out.println("Count: " + count);
        notifyAll(); // 唤醒所有等待的线程
    }

    public static void main(String[] args) {
        WaitNotifyExample example = new WaitNotifyExample();

        // 创建两个线程进行增加操作
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                example.increment();
                try {
                    Thread.sleep(100); // 模拟耗时操作
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                example.increment();
                try {
                    Thread.sleep(150); // 模拟耗时操作,使两个线程交替执行
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

在这个例子中,当count达到5时,调用wait()的线程会等待,直到其他线程调用notifyAll()唤醒它。这样可以实现线程间的简单协作。但是,需要注意的是,wait()notify()/notifyAll()的使用需要谨慎,因为它们可能会导致死锁或活锁等问题。

7. 请解释Java中的Lock接口和ReentrantLock类,并比较它们与synchronized的区别。

Lock接口是Java并发包java.util.concurrent.locks中的一个重要接口,它提供了比synchronized更灵活的锁控制。ReentrantLockLock接口的一个实现类,它支持可重

学习教程(传送门)

1、掌握 JAVA入门到进阶知识(持续写作中……
2、学会Oracle数据库用法(创作中……
3、手把手教你vbs脚本制作(完善中……
4、牛逼哄哄的 IDEA编程利器(编写中……
5、吐血整理的 面试技巧(更新中……
在这里插入图片描述

往期文章

 第一章:日常_JAVA_面试题集15(含答案)
 第二章:日常_JAVA_面试题集14(含答案)
平安壹钱包面试官:请你说一下Mybatis的实现原理
Java开发-热点-热门问题精华核心总结-推荐
 往期文章大全……
在这里插入图片描述

一键三连 一键三连 一键三连~
在这里插入图片描述

本人详解
作者:王文峰,参加过 CSDN 2020年度博客之星,《Java王大师王天师》
公众号:JAVA开发王大师,专注于天道酬勤的 Java 开发问题
中国国学、传统文化和代码爱好者的程序人生,期待你的关注和支持!本人外号:神秘小峯 山峯
转载说明:务必注明来源(注明:作者:王文峰哦)

一键三连 一键三连 一键三连~
以上就是今天的内容,关注我,不迷路

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值