码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • Java面试题(每天10题)-------连载(28)


    目录

    多线程篇

    1、线程和进程有什么区别?

    2、线程实现的方式有几种?

    3、高并发、任务执行时间短的业务怎么使用线程池?并发布高、任务执行时间长的业务怎么使用线程池?并发高业务执行时间长的业务怎么使用线程池?

    4、如果你提交任务时,线程池队列已满,只是会发生什么?

    5、锁的等级:方法锁、对象锁、类锁

    6、如果同步块内的线程抛出异常会发生什么?

    7、并发线程(concurrency)并发编程(parallellism)有什么区别?

    8、如何保证多线程下i++结果正确?

    9、一个线程如果出现了运行时异常会怎么样?

    10、如何再两个线程之间共享数据?


    多线程篇

    1、线程和进程有什么区别?

    1. 进程是系统进⾏资源分配的基本单位,有独⽴的内存地址空间
    2. 线程是 CPU 独⽴运⾏和独⽴调度的基本单位,没有单独地址空间,有独⽴的栈,局部变量,寄存器, 程序计数器等。
    3. 创建进程的开销⼤,包括创建虚拟地址空间等需要⼤量系统资源。

    4. 创建线程开销⼩,基本上只有⼀个内核对象和⼀个堆栈。
    5. ⼀个进程⽆法直接访问另⼀个进程的资源;同⼀进程内的多个线程共享进程的资源。
    6. 进程切换开销⼤,线程切换开销⼩;进程间通信开销⼤,线程间通信开销⼩。
    7. 线程属于进程,不能独⽴执⾏。每个进程⾄少要有⼀个线程,成为主线程。

    2、线程实现的方式有几种?

    1. 继承 Thread 类,重写 run ⽅法
    2. 实现 Runnable 接⼝,重写 run ⽅法,实现 Runnable 接⼝的实现类的实例对象作为 Thread 构造函数的 target
    3. 实现Callable接⼝通过FutureTask包装器来创建Thread线程
    4. 通过线程池创建线程
    1. public class ThreadDemo03 {
    2. public static void main(String[] args) {
    3. Callable oneCallable = new Tickets();
    4. FutureTask oneTask = new FutureTask(oneCallable);
    5. Thread t = new Thread(oneTask);
    6. System.out.println(Thread.currentThread().getName());
    7. t.start();
    8. }
    9. }
    10. class Tickets implements Callable{
    11. //重写call⽅法
    12. @Override
    13. public Object call() throws Exception {
    14. // TODO Auto-generated method stub
    15. System.out.println(Thread.currentThread().getName()+"-->我是通过实现Callable接⼝通过FutureTask包装器来实现的线程"
    16. return null;
    17. }
    18. }
    19. 3、高并发、任务执行时间短的业务怎么使用线程池?并发布高、任务执行时间长的业务怎么使用线程池?并发高业务执行时间长的业务怎么使用线程池?

      1. ⾼并发、任务执⾏时间短的业务:线程池线程数可以设置为 CPU 核数 +1 ,减少线程上下⽂的切换。
      2. 并发不⾼、任务执⾏时间⻓的业务要区分开看:
      a. 假如是业务时间⻓集中在 IO 操作上,也就是 IO 密集型的任务,因为 IO 操作并不占⽤ CPU ,所以不要让所有的 CPU闲下来,可以加⼤线程池中的线程数⽬,让CPU 处理更多的业务
      b. 假如是业务时间⻓集中在计算操作上,也就是计算密集型任务,这个就没办法了,和(1)⼀样吧,线程池中的线程数设置得少⼀些,减少线程上下⽂的切换
      3. 并发⾼、业务执⾏时间⻓,解决这种类型任务的关键不在于线程池⽽在于整体架构的设计,看看这些业务⾥⾯某些数据是否能做缓存是第⼀步,增加服务器是第⼆步,⾄于线程池的设置,设置参考(2)。最后,业务执⾏时间⻓的问题,也可能需要分析⼀下,看看能不能使⽤中间件对任务进⾏拆分和解耦。

      4、如果你提交任务时,线程池队列已满,只是会发生什么?

      1、如果你使⽤的 LinkedBlockingQueue ,也就是⽆界队列的话,没关系,继续添加任务到阻塞队列中等待执⾏,因为LinkedBlockingQueue可以近乎认为是⼀个⽆穷⼤的队列,可以⽆限存放任务;
      2 、如果你使⽤的是有界队列⽐⽅说 ArrayBlockingQueue 的话,任务⾸先会被添加到 ArrayBlockingQueue 中,ArrayBlockingQueue满了,则会使⽤拒绝策略 RejectedExecutionHandler 处理满了的任务,默认是 AbortPolicy。

      5、锁的等级:方法锁、对象锁、类锁

      1. ⽅法锁( synchronized 修饰⽅法时)
      a. 通过在⽅法声明中加⼊ synchronized 关键字来声明 synchronized ⽅法。
      b. synchronized ⽅法控制对类成员变量的访问:
      c. 每个类实例对应⼀把锁,每个 synchronized ⽅法都必须获得调⽤该⽅法的类实例的锁⽅能执⾏,否则所属线程阻塞,⽅法⼀旦执⾏,就独占该锁 ,直到从该⽅法返回时才将锁释放,此后被阻塞的线程⽅能获得该锁,重新进⼊可 执⾏状态。这种机制确保了同⼀时刻对于每⼀个类实例,其所有声明为 synchronized 的成员函数中⾄多只有⼀个处于可执⾏状态,从⽽有效避免了类成员变量的访问冲突。
      2. 对象锁( synchronized 修饰⽅法或代码块)
      a. 当⼀个对象中有 synchronized method 或 synchronized block 的时候调⽤此对象的同步⽅法或进⼊其同步区域时,就必须先获得对象锁。如果此对象的对象锁已被其他调⽤者占⽤,则需要等待此锁被释放。(⽅法锁也是对象锁)
      b. java 的所有对象都含有 1 个互斥锁,这个锁由 JVM ⾃动获取和释放。线程进⼊ synchronized ⽅法的时候获取该对象的锁,当然如果已经有线程获取了这个对象的锁,那么当前线程会等待;synchronized ⽅法正常返回或者抛异常⽽终⽌,JVM 会⾃动释放对象锁 。这⾥也体现了⽤ synchronized 来加锁的 1 个好处,⽅法抛异常的时候,锁仍然可以由JVM来⾃动释放。 
      3. 类锁( synchronized 修饰静态的⽅法或代码块)
      a. 由于⼀个 class 不论被实例化多少次,其中的静态⽅法和静态变量在内存中都只有⼀份。所以,⼀旦⼀个静态的⽅法被申明为synchronized 。此类所有的实例化对象在 调⽤此⽅法 ,共⽤同⼀把锁,我们称之为类锁。
      4. 对象锁是⽤来控制实例⽅法之间的同步,类锁是⽤来控制静态⽅法(或静态变量互斥体)之间的同步。

      6、如果同步块内的线程抛出异常会发生什么?

       synchronized⽅法正常返回或者抛异常⽽终⽌,JVM会⾃动释放对象锁

      7、并发线程(concurrency)并发编程(parallellism)有什么区别?

      1. 解释⼀:并⾏是指两个或者多个事件在同⼀时刻发⽣;⽽并发是指两个或多个事件在同⼀时间间隔发⽣。
      2. 解释⼆:并⾏是在不同实体上的多个事件,并发是在同⼀实体上的多个事件。
      3. 解释三:在⼀台处理器上“同时”处理多个任务,在多台处理器上同时处理多个任务。如 hadoop 分布式集群。
      所以并发编程的目标是充分的利用处理器的每一个核,以达到最高的处理性能。

      8、如何保证多线程下i++结果正确?

      1. volatile 只能保证你数据的可⻅性,获取到的是最新的数据,不能保证原⼦性;
      2. ⽤ AtomicInteger 保证原⼦性。
      3. synchronized 既能保证共享变量可⻅性,也可以保证锁内操作的原⼦性。

      9、一个线程如果出现了运行时异常会怎么样?

      1、如果这个异常没有被捕获的话,这个线程就停⽌执⾏了。
      2.、 另外重要的⼀点是:如果这个线程持有某个对象的监视器,那么这个对象监视器会被⽴即释放。

      10、如何再两个线程之间共享数据?

      通过在线程之间共享对象就可以了,然后通过wait/notify/notifyAll、await/signal/signalAll进⾏唤起和等待,⽐⽅说阻塞队列BlockingQueue就是为线程之间共享数据⽽设计的。

      1、 卖票系统:
      1. public class Ticket implements Runnable {
      2. private int ticket = 10;
      3. public void run() {
      4. while (ticket > 0) {
      5. ticket--;
      6. System.out.println("当前票数为:" + ticket);
      7. }
      8. }
      9. }
      10. package 多线程共享数据;
      11. public class SellTicket {
      12. public static void main(String[] args) {
      13. Ticket t = new Ticket();
      14. new Thread(t).start();
      15. new Thread(t).start();
      16. }
      17. }

      2、银行存取款 

      1. public class MyData {
      2. private int j = 0;
      3. public synchronized void add() {
      4. j++;
      5. System.out.println("线程" + Thread.currentThread().getName() + "j为:" + j);
      6. }
      7. public synchronized void dec() {
      8. j--;
      9. System.out.println("线程" + Thread.currentThread().getName() + "j为:" + j);
      10. }
      11. public int getData() {
      12. return j;
      13. }
      14. }
      15. public class AddRunnable implements Runnable {
      16. MyData data;
      17. public AddRunnable(MyData data) {
      18. this.data = data;
      19. }
      20. public void run() {
      21. data.add();
      22. }
      23. }
      24. public class DecRunnable implements Runnable {
      25. MyData data;
      26. public DecRunnable(MyData data) {
      27. this.data = data;
      28. }
      29. public void run() {
      30. data.dec();
      31. }
      32. }
      33. public class TestOne {
      34. public static void main(String[] args) {
      35. MyData data = new MyData();
      36. Runnable add = new AddRunnable(data);
      37. Runnable dec = new DecRunnable(data);
      38. for (int i = 0; i < 2; i++) {
      39. new Thread(add).start();
      40. new Thread(dec).start();
      41. }
      42. }
      43. }

    20. 相关阅读:
      激光雷达「超预期」放量
      git 删除某一次的提交(commit)
      「Redis缓存」Redis 缓存数据库一致性手撕面答
      什么是分布式锁?几种分布式锁分别是怎么实现的?
      理解HTTPS/TLS/SSL(二)可视化TLS握手过程并解密加密数据
      Java基础:Java类与对象
      Conda环境配置常用
      机器学习_10、集成学习-AdaBoost
      vue3 hooks demo
      赞!图像几何三维重建代码实战教程来啦!深度计算+点云处理+网格重建优化+纹理贴图!
    21. 原文地址:https://blog.csdn.net/tgdmjhf/article/details/134324808
      • 最新文章
      • 攻防演习之三天拿下官网站群
        数据安全治理学习——前期安全规划和安全管理体系建设
        企业安全 | 企业内一次钓鱼演练准备过程
        内网渗透测试 | Kerberos协议及其部分攻击手法
        0day的产生 | 不懂代码的"代码审计"
        安装scrcpy-client模块av模块异常,环境问题解决方案
        leetcode hot100【LeetCode 279. 完全平方数】java实现
        OpenWrt下安装Mosquitto
        AnatoMask论文汇总
        【AI日记】24.11.01 LangChain、openai api和github copilot
      • 热门文章
      • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
        奉劝各位学弟学妹们,该打造你的技术影响力了!
        五年了,我在 CSDN 的两个一百万。
        Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
        面试官都震惊,你这网络基础可以啊!
        你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
        心情不好的时候,用 Python 画棵樱花树送给自己吧
        通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
        13 万字 C 语言从入门到精通保姆级教程2021 年版
        10行代码集2000张美女图,Python爬虫120例,再上征途
      Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
      正则表达式工具 cron表达式工具 密码生成工具

      京公网安备 11010502049817号