Day280.线程8大基础知识---面试题总结 -Juc

Posted 阿昌喜欢吃黄桃

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Day280.线程8大基础知识---面试题总结 -Juc相关的知识,希望对你有一定的参考价值。

线程8大基础知识—面试题总结

1、有多少种实现线程的方法?

2种,但本质只有1种;继承Thread类、实现Runnable接口。他们的实现线程方式无非都是通过这两种方式实现


2、实现Runnable接口和继承Thread类哪种方式好?

实现Runnable接口的方式要好

  • 节省资源
  • 解耦,run()方法跟线程继承应该是分开的
  • 接口可被多实现

3、一个线程两次调用start()方法会出现什么情况?为什么?

会报错,因为每个线程运行就一次结束后,他的生命周期就结束了,关闭线程后他会将线程设置为关闭状态;

如果还想要运行,就只能重新建一个线程,再执行start()方法。


4、既然start()会调用run()方法,那为什么不直接调用run()方法呢?

因为调用start()会启用线程,run()只是一个普通方法


5、如何停止线程

通过interrupt中断的方式停止线程,并且要求在里面有进行中断响应判断,相互配合才可以正确关闭;

不推荐使用stop()…等已经被弃用的方法


6、如何处理不可中断的阻塞

没有一个套路,需要根据不同情况,进行不同的处理;如果没有办法处理,那就让他苏醒后让他更快的感受到这次的中断


7、线程有哪几种状态?生命周期是什么?

New新建线程;Runnable已启动线程;Blocked阻塞线程;Waiting等待线程;TimeWaiting时间等待线程;Terminated终止线程

image-20210521203651798


8、用程序实现两种线程交替打印0-100的奇偶数

/******
 @author 阿昌
 @create 2021-05-23 20:05
  *******
  *  两个线程交替打印 0 - 100 的奇偶数,用wait和notify
 */
public class WaitNotifyPrintOddEven {

    private static int count = 0;
    private static final Object lock = new Object();

    //主函数
    public static void main(String[] args) {
        TurningRounder turningRounder = new TurningRounder();
        Thread even = new Thread(turningRounder);
        Thread odd = new Thread(turningRounder);

        even.start();
        odd.start();
    }

    static class TurningRounder implements Runnable {
        @Override
        public void run() {
            while (count <= 100) {
                synchronized (lock) {
                    System.out.println(Thread.currentThread().getName() + "," + count++);
                    lock.notify();
                    if (count <= 100) {
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }
}

9、手写生产者消费者设计模式

/******
 @author 阿昌
 @create 2021-05-22 20:58
 *******
 *  用wait/notify来实现 生产者消费者模式
 */
public class ProducerConsumerModel {
    //主函数
    public static void main(String[] args) {
        EventStorage eventStorage = new EventStorage();
        Consumer1 consumer = new Consumer1(eventStorage);
        Producer1 producer = new Producer1(eventStorage);

        Thread threadConsumer = new Thread(consumer);
        Thread threadProducer = new Thread(producer);

        threadConsumer.start();
        threadProducer.start();
    }
}

//生产者
class Producer1 implements Runnable{
    private EventStorage storage;

    public Producer1(EventStorage storage) {
        this.storage = storage;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            storage.put();
        }
    }
}

//消费者
class Consumer1 implements Runnable{
    private EventStorage storage;

    public Consumer1(EventStorage storage) {
        this.storage = storage;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            storage.take();
        }
    }
}

//队列
class EventStorage{
    private int maxSize;
    private LinkedList storage;

    public EventStorage(){
        this.maxSize=10;
        storage = new LinkedList<>();
    }

    //生成产品
    public synchronized void put(){
        //如果满了
        while (storage.size()==maxSize){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        //如果没满
        storage.add(new Date());
        System.out.println("生产者生产了产品,仓库里有了"+storage.size()+"个产品");
        notify();
    }

    //消费产品
    public synchronized void take(){
        //如果空了
        while (storage.size()<=0){
            try { 
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //如果没空
        System.out.println("消费者消费了产品,拿到了"+storage.poll()+",现在仓库还剩下"+storage.size());
        notify();
    }
}

十、为什么wait()需要在同步代码块内使用,而sleep()不需要

防范线程等待问题,wait()会释放锁,而sleep不释放锁


十一、为什么线程通信的方法wait(),notify和notifyAll()被定义在Object类里?二sleep()定义在Thread类中?

因为Java每个对象都作为一个锁的单位


十二、wait方法是Object对象的,那在Thread.wait调用会怎么样?

Thread类执行完毕后会自动对 线程对象 执行notify()


十三、notify和notifyAll的区别

notify:随机唤醒一个阻塞状态的线程

notifyAll:唤醒全部阻塞状态线程


十四、notifyAll之后所有的线程都会再次抢夺锁,如果某线程抢夺失败会怎么样?

在入口级再等待下次锁对象被释放,再去抢夺锁


十五、suspend()和resume()来阻塞线程可以吗?为什么?

可以的,会有数据风险问题


十六、wait/notify、sleep异同(方法属于哪个对象?线程状态怎么切换)

前者属于Object类;后者属于Thread类;前着释放锁,后者不释放锁;

他们都会使线程进入阻塞状态


十七、在join期间线程处于哪种状态?

处于waiting状态

join方法里面底层其实就是调用wait方法,并通过Thread类底层调用notify唤All醒


十八、守护线程和普通线程的区别

守护线程服务于普通线程,当普通线程全部被关闭后JVM也会关闭,但是守护线程没有被关闭完,JVM也会关闭


十九、我们是否需要给线程设置为守护线程?

不需要,因为Java所提供的守护线程足够使用


二十、run方法是否可以抛出异常,如果抛出异常,线程状态会怎么样?

二十一、线程中如何处理某个未处理异常?

通过实现UnCaughtExceptionHanlder来捕获这个异常

二十二、什么是多线程的上下文切换?

上下文就是线程运行执行的进度环境,切换就是当他被阻塞切换为其他线程执行后,要保存这个环境和进度所消耗的资源

以上是关于Day280.线程8大基础知识---面试题总结 -Juc的主要内容,如果未能解决你的问题,请参考以下文章

Java核心面试宝典Day14“线程池”高频面试题总结!✊✊✊

Java核心面试宝典Day14“线程池”高频面试题总结!✊✊✊

Java核心面试宝典Day12“Java虚拟机”相关面试题大总结

Java核心面试宝典Day12“Java虚拟机”相关面试题大总结

面试题:各大公司Java后端开发面试题总结 !=!未看

Day530.图灵学院之面试题④ -面经