并发编程面试题0

news2024/12/24 21:34:29

并发编程

1、并行和并发有什么区别?

并行和并发都是指多个任务同时执行的概念,但是它们之间有着明显的区别
并行:多个任务在同一时间同时执行,通常需要使用多个处理器或者多核处理器来实现。例如,一个多核CPU的计算机同时执行多个进程或多个线程是,就是采用并行的方式来处理任务的,这样能提高计算机的处理效率。

并发:多个任务同时进行,但是这些任务的执行是交替进行的,即一个任务执行一段时间后,再执行另一个任务。它是通过操作系统的协作调度来实现各个任务的切换,达到看上去同时进行的效果。例如一个多线程程序中的多个线程就是同时运行的,但是因为一个CPU只能处理一个线程,所以在任意时刻只有一个线程在执行,线程之间会通过竞争的方式来获取CPU的时间片。

在这里插入图片描述

2、线程有几种创建方式

在Java中,线程的创建主要有以下4种方式:
1、继承Thread类
通过继承Thread类并重写其run()方法,可以创建一个新的线程。然后,可以创建这个类的实例并调用其start()方法来启动线程。

public class Test3 {
    public static void main(String[] args) {
        // 创建实例。
        MyThread myThread = new MyThread();
        // 设置线程的name
        myThread.setName("myThread");
        // 调用start()方法来启动线程
        myThread.start();
        
        // 获取主线程的name
        System.out.println(Thread.currentThread().getName());
    }


}

// 1、通过继承Threadl类创建线程
class MyThread extends Thread {
    @Override
    public void run() {
        // 线程执行的代码,获取线程的name
        System.out.println(Thread.currentThread().getName());
    }
}

2、实现Runnable接口
通过实现Runnable接口并重写其run()方法,可以创建一个任务对象。然后,可以创建Thread类的实例并将任务对象作为参数传递给其构造函数,最后调用start()方法来启动线程。这种方式允许你继承其他类,因为Java不支持多重继承。

public class Test3 {
    public static void main(String[] args) {
        // 创建任务对象。
        MyThread2 myThread2 = new MyThread2();
        // 创建Thread类的实例并将任务对象作为参数传递给其构造函数
        Thread thread = new Thread(myThread2);
        // 设置线程的name
        thread.setName("myThread2");
        // 调用start()方法来启动线程
        thread.start();
        
        // 获取主线程的name
        System.out.println(Thread.currentThread().getName());
    }


}

// 2、通过实现Runnable接口来创建线程
class MyThread2 implements Runnable {
    @Override
    public void run() {
        // 线程执行的代码
        System.out.println(Thread.currentThread().getName());
    }
}

3、实现Callable接口

Callable接口类似于Runnable,但允许线程执行的任务有返回值,并且可以抛出异常。Future接口表示异步计算的结果;·可以使用ExecutorService来提交Callable任务,并使用返回的Future对象来检索结果或检查任务是否完成。

public class Test3 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 1、通过FutureTask启动线程
        FutureTask<String> futureTask = new FutureTask<>(new MyThread3());
        Thread thread = new Thread(futureTask);
        thread.setName("myThread3");
        thread.start();
        // 等待任务完成并获取结果
        System.out.println(futureTask.get());

        // 2、通过ExecutorService启动线程
        // 创建一个ExecutorService
        ExecutorService executorService = Executors.newSingleThreadExecutor();

        // 提交Callable任务,并获取Future对象
        Future<String> future = executorService.submit(new MyThread3());

        // 等待任务完成并获取结果
        System.out.println(future.get());

        // 关闭ExecutorService
        executorService.shutdown();
    }


}

// 3、通过实现Callable接口来创建线程
class MyThread3 implements Callable<String> {

    @Override
    public String call() throws Exception {

        return Thread.currentThread().getName();
    }
}

4、使用线程池

尽管线程池本身不是直接创建线程的方式,但它是一种管理线程的高效方式。你可以使用ExecutorService框架(如Executors类提供的静态工厂方法)来创建和管理线程池。线程池中的线程可以被重复利用,以执行多个任务,从而减少了线程创建和销毁的开销。

3、Java线程启动为什么是调用start()方法而不是直接调用run()方法?

JVM执行start()方法,会先创建一个线程并使其经历其生命周期的各个阶段(例如,新建、就绪、运行、阻塞、死亡等),当新线程被启动后,它会自动调用run()方法,这才会起到多线程的效果;如果直接调用run()方法,就相当于调用了一个普通方法,程序中依然只有主线程这一个线程。

通过调用start()方法启动新线程,可以实现并发执行多个任务,提高程序的效率。如果我们直接调用run()方法,那么这些任务将只能在主线程中顺序执行,无法实现并发。但是,一个线程的start()方法不能被重复调用,而run()方法可以

4、线程有哪些常用的调度方法

1、设置线程优先级:
Java中的线程优先级通过整数表示,范围从1到10。可以使用Thread类的setPriority()方法来设置线程的优先级。更高优先级的线程倾向于比低优先级的线程更早地执行,但线程优先级并不保证绝对的执行顺序,而是提供了一个提示,让调度器更可能将CPU时间分配给优先级较高的线程

2、线程调度相关的线程状态转换方法:
thread.start(): 启动一个新线程,使其进入就绪状态。调用此方法后,线程将自动调用其run()方法。

thread.sleep(long millis): 休眠,使当前线程(即调用该方法的线程)暂停执行一段时间(以毫秒为单位),当休眠结束后,线程自动转为就绪状态

thread.yield(): 让步,暂停当前正在执行的线程对象,并执行其他线程。但具体哪个线程将恢复执行取决于操作系统的线程调度算法。

thread.join(): 等待,等待该线程终止。调用某线程的join()方法将使得当前线程暂停执行,直到目标线程执行完毕

object.wait(): 等待,Object类中的wait()方法,使当前线程(即调用该方法的线程)等待,直到其他线程调用此对象的notify()方法或notifyAll()方法。

object.wait(long): 等待,相比wait()方法多了一个超时参数,如果线程调用这个方法,没有在指定时间内被其他线程唤醒,那么这个方法会因超时而返回。

thread.interrupt(): 中断线程。如果线程在等待、睡眠或进行某些阻塞操作,则interrupt()方法会将其唤醒并抛出InterruptedException。

thread.isInterrupted()

thread.interrupted()

3、线程等待和通知:
object.notify(): 通知,唤醒在此对象监视器上等待的单个线程选择是任意性的

object.notifyAll(): 通知,唤醒在此对象监视器上等待的所有线程

public class Test4 {
    public static void main(String[] args) throws Exception {

        Object lock = new Object();

        Thread thread1 = new Thread(() -> {
            try {
                synchronized (lock) {
                    System.out.println(Thread.currentThread().getName() + "线程进入永久等待" + LocalTime.now());
                    // 使线程进入等待,直到被唤醒
                    lock.wait();
                    System.out.println(Thread.currentThread().getName() + "线程永久等待被唤醒" + LocalTime.now());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        }, "thread1");

        Thread thread2 = new Thread(() -> {
            try {
                synchronized (lock) {
                    System.out.println(Thread.currentThread().getName() + "线程进入永久等待" + LocalTime.now());
                    // 使线程进入等待,直到被唤醒,没有被唤醒则等待3s
                    lock.wait(3000);
                    System.out.println(Thread.currentThread().getName() + "线程永久等待被唤醒" + LocalTime.now());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        }, "thread2");

        // 启动线程
        thread1.start();
        thread2.start();

        // 休眠1s,让thread1先执行
        Thread.sleep(1000);
        synchronized (lock) {
            // 随机唤醒在此对象监视器上的一个线程
            lock.notify();
            // 唤醒在此对象监视器上的所有线程
//            lock.notifyAll();
        }
        // 使主线程暂停执行,直到thread1线程执行完毕。
        thread1.join();
        thread2.join();

    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1945475.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

国内大陆地区huggingface连接不上的解决方案

简介 本文主要介绍国内大陆地区huggingface连接不上的解决方案,希望能对学习大模型的同学们有所帮助。 1. 背景 最近有不少同学反应无法正常下载huggingface的模型文件,亲自尝试使用git clone下载huggingface上的大模型文件时,也同样无法正常下载,以Meta-Llama-3-8B为例…

美食地图开发

调用地图接口展示数据库录入的不同类别地址信息&#xff0c;提供导航服务&#xff0c;手机端电脑端自适应。 语音介绍使用微软的tts接口可选不同语音性别生成

【数据结构】AVL树(图文解析 + 代码实现)

目录 1、AVL树的概念 2、AVL树结点的定义 3、AVL树的插入 4、AVL树的旋转 4.1 左单旋 4.2 右单旋 4.3 右左双旋 4.4 左右双旋 5、AVL树的验证 6、AVL树的性能 前面对map/multimap/set/multiset进行了简单的介绍&#xff0c;会大仙&#xff0c;这几个容器有个共同点是…

力扣 二分查找

二分查找基础篇。 题目 class Solution {public int searchInsert(int[] nums, int target) {int l 0, r nums.length - 1;while(l < r) {int mid l((r-l)>>1);//(lr)/2if(nums[mid]<target)lmid1;else rmid-1;}return l;//处理边界&#xff0c;设定数组的左半…

剪画小程序:相册里的视频变成微信动图表情包,很简单!

Hello&#xff0c;各位小伙伴们好啊&#xff01; 今天小画告诉大家怎么把微信里的视频变成微信专属表情包 让你的聊天变得更加有趣&#xff01; 一、首先&#xff0c;我们要将那些有趣的视频保存到手机相册里 在微信聊天时遇到眼前一亮的视频或在短视频平台上刷到的有趣的视…

linux虚拟机主机配置网卡

问题复现 我的虚拟主机了连不上远程工具windTerm ,但是我的另一台虚拟主机可以连上 我的解决思路 ping ip 地址 发现能够 ping 通 查看 ifconfig 配置信息 我对比另一个虚拟主机 发现了我的子网掩码netmask有问题 解决方式 第一种 连接配置 配置 ipv4.addresses 192.168.1…

JAVA毕业设计153—基于Java+Springboot+小程序的校园维修管理系统小程序(源代码+数据库)

毕设所有选题&#xff1a; https://blog.csdn.net/2303_76227485/article/details/131104075 基于JavaSpringboot小程序的校园维修管理系统小程序(源代码数据库)153 一、系统介绍 本项目分为用户、维修员、管理员三种角色 1、用户&#xff1a; 注册、登录、报修申报、报修…

顺序表和单链表的经典算法题

目录 前言 一、基础思想&#xff08;数组&#xff09; 1. 移除元素 2.删除有序元素的重复项 3.合并两个有序数组 二、单链表算法 1.移除链表元素 2.翻转链表 3.合并两个有序的链表 前言 Hello,小伙伴们&#xff0c;今天我们来做一个往期知识的回顾&#xff0c;今天我将…

Spring源码(六)--BeanFactory 实现与继承关系

BeanFactory 实现与继承关系 这些接口和类的源码&#xff0c; 每一个都可以看一下。 ListableBeanFactory 由bean工厂实现的BeanFactory接口的扩展&#xff0c;这些bean工厂可以枚举它们所有的bean实例&#xff0c;而不是按客户端请求逐个按名称进行bean查找。 Hierarchic…

C# yaml 配置文件的用法(一)

目录 一、简介 二、yaml 的符号 1.冒号 2.短横杆 3.文档分隔符 4.保留换行符 5.注释 6.锚点 7.NULL值 8.合并 一、简介 YAML&#xff08;YAML Aint Markup Language&#xff09;是一种数据序列化标准&#xff0c;广泛用于配置文件、数据交换和存储。YAML的设计目标是…

Kotlin 协程 — 基础

Kotlin 协程 — 基础 协程已经存在一段时间了&#xff0c;关于它的各种文章也很多。但我发现想要了解它还比较费时&#xff0c;所以我花了一段时间才真正理解了协程的基础知识以及它的工作原理。因此&#xff0c;我想分享一些我理解到的内容。 什么是协程&#xff1f; 协程代表…

【MySQL进阶之路 | 高级篇】事务的ACID特性

1. 数据库事务概述 事务是数据库区别于文件系统的重要特性之一&#xff0c;当我们有了事务就会让数据库始终保持一致性&#xff0c;同时我们还能通过事务的机制恢复到某个时间点&#xff0c;这样可以保证给已提交到数据库的修改不会因为系统崩溃而丢失。 1.1 基本概念 事务&…

企业微信获客助手广告平台深度回传/双回传设置教程参考

很多商家在使用【转化宝】进行推广时只采用了单回传&#xff0c;其实很多情况下单回传即可满足推广模型优化需求&#xff1b;但是最近很多专业化广告运营的代投或运营都开始采用双回传&#xff0c;【转化宝】支持抖音巨量引擎、百度营销广告、快手广告、腾讯广告等均支出深度优…

微信小程序开发:项目程序代码构成

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

开源模型应用落地-LangChain高阶-记忆组件-ConversationBufferMemory正确使用(一)

一、前言 LangChain 的记忆组件发挥着至关重要的作用&#xff0c;其旨在协助大语言模型&#xff08;LLM&#xff09;有效地留存历史对话信息。通过这一功能&#xff0c;使得大语言模型在对话过程中能够更出色地维持上下文的连贯性和一致性&#xff0c;进而能够像人类的记忆运作…

【网络安全】构建稳固与安全的网络环境:从“微软蓝屏”事件中汲取的教训

发生什么事了&#xff1f; 近日&#xff0c;一次由微软视窗系统软件更新引发的全球性“微软蓝屏”事件&#xff0c;不仅成为科技领域的热点新闻&#xff0c;更是一次对全球IT基础设施韧性与安全性的深刻检验。这次事件&#xff0c;源于美国电脑安全技术公司“众击”提供的一个…

中断和EXIT原理介绍

中断和EXIT原理介绍 一、中断的介绍&#xff1f;二、EXIT的介绍1.EXIT作用2.EXIT的详情3.EXIT中AFIO复用的作用4.STM32中AFIO复用作用 一、中断的介绍&#xff1f; 二、EXIT的介绍 EXTI&#xff08;Extern Interrupt&#xff09;外部中断 1.EXIT作用 EXTI可以监测指定GPIO口…

Java学习笔记(五)数组、冒泡排序

Hi i,m JinXiang ⭐ 前言 ⭐ 本篇文章主要介绍Java数组、冒泡排序使用以及部分理论知识 &#x1f349;欢迎点赞 &#x1f44d; 收藏 ⭐留言评论 &#x1f4dd;私信必回哟&#x1f601; &#x1f349;博主收将持续更新学习记录获&#xff0c;友友们有任何问题可以在评论区留言 …

力扣SQL50 指定日期的产品价格 双重子查询 coalesce

Problem: 1164. 指定日期的产品价格 coalesce 的使用 简洁版 &#x1f468;‍&#x1f3eb; 参考题解 select distinct p1.product_id,coalesce((select p2.new_pricefrom Products p2where p2.product_id p1.product_id and p2.change_date < 2019-08-16order by p2.…

Web前端Promise

Promise介绍与使用 Promise是什么&#xff1f; 1.抽象表达&#xff1a; Promise是一门新的技术&#xff08;ES6规范&#xff09;Promise是JS中进行异步编程的新解决方案备注&#xff1a;旧方案是单纯使用回调函数 2.具体表达&#xff1a; 从语法上来说&#xff1a;Promise…