【Docker】进阶之路:(六)Docker镜像

【Docker】进阶之路:(六)Docker镜像

  • 理解镜像构成
  • 获取镜像
  • 列出镜像
  • 删除本地镜像
  • 定制镜像
    • 使用Dockerfile定制镜像
  • 使用docker build命令+Dockerfile文件定制镜像

理解镜像构成

镜像由多个层组成,每层叠加之后,从外部看来就如一个独立的对象。镜像内部是一个精简的操作系统(OS),同时还包含应用运行所必须的文件和依赖包。因为容器的设计初衷就是快速和小巧,所以镜像通常都比较小。前面多次提到镜像就像停止运行的容器(类)。实际上,可以停止某个容器的运行,并从中创建新的镜像。因此,镜像可以理解为一种构建时(build-time)结构,而容器可以理解为一种运行时(run-time)结构。
在这里插入图片描述

获取镜像

当用户在创建容器的时候,可以自己创建所需要的镜像。但是,在绝大多数情况下,用户选择的是从 Docker 镜像仓库中查找所需要的镜像。找到之后,将其从镜像仓库中下载到本地使用。
首先需要先从镜像仓库服务中拉取镜像。常见的镜像仓库服务是 Docker Hub,但是也存在其他镜像仓库服务。拉取操作会将镜像下载到本地 Docker 主机,可以使用该镜像启动一个或者多个容器。
Docker提供了docker search命令来查找远程镜像仓库上面的镜像。该命令的使用方法非常简单,其语法如下

docker search keyword

列出镜像

如果用户想要查看已经下载到本地的镜像,可以使用dockerimages命令。该命令可以直接使用,不加任何参数。

[root@docker ~]# docker images
REPOSITORY           TAG                 IMAGE ID       CREATED         SIZE
circle/ubuntu        1.0                 34035f46d2c6   6 seconds ago   72.8MB
circledba/kingbase   v008r006c007b0024   df101ff5974d   41 hours ago    12.4GB
tomcat               latest              fb5657adc892   23 months ago   680MB
ubuntu               latest              ba6acccedd29   2 years ago     72.8MB
centos               7                   eeb6ee3f44bd   2 years ago     204MB

其中第一列为镜像名称,第二列为镜像标签,默认标签为latest:最后一个标签。第三列为镜像ID,第四列为镜像创建时间,第五列为镜像的大小。

删除本地镜像

对于当前系统中已经不需要的镜像,为了节省存储空间,管理员可以将其删除。删除镜像使用docker rmi命令,其中,rmi中的字母i表示镜像。该命令的基本语法如下:

docker rmi image ...

其中image为镜像名称。用户可以同时删除多个镜像,多个镜像名称之间用空格隔开。例如,下面的命令删除名称为tomcat的本地镜像:

[root@docker ~]# docker rmi tomcat
Untagged: tomcat:latest
Untagged: tomcat@sha256:9dee185c3b161cdfede1f5e35e8b56ebc9de88ed3a79526939701f3537a52324
Deleted: sha256:fb5657adc892ed15910445588404c798b57f741e9921ff3c1f1abe01dbb56906
Deleted: sha256:2b4d03a9ce5e200223e5c398d4739d23dd19ad0d6e692cfc65ba3a8fae838444
Deleted: sha256:35c5ea12be1face90896b3a52afc28433885c4448a6c5cfe07561f82365cd18e
Deleted: sha256:6830091c111746b7534960d17f6c156be45d8dcfe0defb06bd427ef38bf49aae
Deleted: sha256:ea82d4efcdfa1c039d722a5a9613c18d3c3a84fbba8efae5e7f13cb3b4ec379f
Deleted: sha256:79a6c362c6b1a580d2d8d33f6d860d45c530f34ff7c0441d36b61aceefdfd656
Deleted: sha256:1788a74c5c86e769f61cd615269eba11c3d7648eac4a85a1ffd2840427820a2f
Deleted: sha256:cbce712ed17923285239f9d9c0528984aef065b7413d68a0290e2c8eecc98f4a
Deleted: sha256:aa56d037ee5925ebf11127c3e1f617874c4ce8bae6b6af7d132b7f7a4a606e6f
Deleted: sha256:97e5f44efb543d466c5847602654a8cb22c9466b61d04988d47ec44b197ea874
Deleted: sha256:11936051f93baf5a4fb090a8fa0999309b8173556f7826598e235e8a82127bce
[root@docker ~]# 

定制镜像

使用Dockerfile定制镜像

镜像的定制实际上就是定制每一层所添加的配置、文件。如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,那么之前提及的无法重复的问题、镜像构建透明性的问题、体积的问题就都会迎刃而解。这个脚本就是 Dockerfile。
Dockerfile 是一个文本文件,其内容包含了一条条的指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。
以下举例说明如何使用Dockerfile来定制 nginx 镜像。

[root@docker ~]# docker run --name webserver -d -p 80:80 nginx
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
a2abf6c4d29d: Pull complete 
a9edb18cadd1: Pull complete 
589b7251471a: Pull complete 
186b1aaa4aa6: Pull complete 
b4df32aa5a72: Pull complete 
a0bcbecc962e: Pull complete 
Digest: sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31
Status: Downloaded newer image for nginx:latest
8dddf86d7a44cb2d19c81fec18c6ea6f4f82626a56133da0723b1a8484f0ec78
[root@docker ~]# 

这条命令会用nginx镜像启动一个容器,容器命名为webserver,并且映射了80端口,这样就可以用浏览器访问nginx服务器。如果是在本机运行的Docker,那么可以直接访问http://localhost;如果是在虚拟机、云服务器上安装的Docker,则需要将localhost转换为虚拟机地址或者实际云服务器地址。
在这里插入图片描述假设需要修改这个页面,改成“Hello,Docker”的文字页面,可以使用docker exec命令进入容器,修改其内容。

[root@docker ~]# docker exec -it webserver bash
root@8dddf86d7a44:/# echo '<h1>Hello,Docker!</h1>' > /usr/share/nginx/html/index.html
root@8dddf86d7a44:/# exit
exit
[root@docker ~]# 

我们以交互式终端方式进入webserver容器,并执行了bash命令,也就是获得一个可操作的Shell。
然后,用

Hello,Docker!

覆盖了/usr/share/nginx/html/index.html的内容。
现在再刷新浏览器的话,会发现页面内容被改变了。我们修改了容器的文件,也就是改动了容器的存储层。可以通过docker diff命令查看具体的改动。

[root@docker ~]#  docker diff webserver
C /etc
C /etc/nginx
C /etc/nginx/conf.d
C /etc/nginx/conf.d/default.conf
C /root
A /root/.bash_history
C /var
C /var/cache
C /var/cache/nginx
A /var/cache/nginx/client_temp
A /var/cache/nginx/fastcgi_temp
A /var/cache/nginx/proxy_temp
A /var/cache/nginx/scgi_temp
A /var/cache/nginx/uwsgi_temp
C /run
A /run/nginx.pid
C /usr
C /usr/share
C /usr/share/nginx
C /usr/share/nginx/html
C /usr/share/nginx/html/index.html
[root@docker ~]# 

我们定制好了变化,希望能将它保存下来形成镜像。当我们运行一个容器的时候,我们做的任何文件修改都会被记录于容器存储层里。而Docker提供了一个docker commit命令,可以将容器的存储层保存下来成为镜像。换句话说,就是在原有镜像的基础上再叠加上容器的存储层,并构成新的镜像。以后我们运行这个新镜像的时候,就会拥有原有容器最后的文件变化。
docker commit的语法格式如下:

docker commit[选项]<容器ID或容器名>[<仓库名>[:<标签>]]

可以用下面的命令将容器保存为镜像:

[root@docker ~]# docker commit --author "Circle-DBA <circledba@qq.com>" --message="修改了默认网页" webserver nginx:v2
sha256:fc43cf21d8a7bb25afe7a07f0fa14f106bc3c210346f5e423bb9c71eef8d3a71
[root@docker ~]# 

其中–author是指定修改的作者,而–message则是记录本次修改的内容。这一点和Git版本控制相似,不过这里的这些信息可以留空省略。
可以在docker image ls中查看这个新定制的镜像:

[root@docker ~]# docker image ls nginx
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
nginx        v2        fc43cf21d8a7   47 seconds ago   141MB
nginx        latest    605c77e624dd   23 months ago    141MB
[root@docker ~]# 

还可以用docker history具体查看镜像内的历史记录,如果比较nginx:latest的历史记录,会发现新增了刚刚提交的这一层。

[root@docker ~]# docker history nginx:v2
IMAGE          CREATED              CREATED BY                                       SIZE      COMMENT
fc43cf21d8a7   About a minute ago   nginx -g daemon off;                             1.19kB    修改了默认网页
605c77e624dd   23 months ago        /bin/sh -c #(nop)  CMD ["nginx" "-g" "daemon…   0B        
<missing>      23 months ago        /bin/sh -c #(nop)  STOPSIGNAL SIGQUIT            0B        
<missing>      23 months ago        /bin/sh -c #(nop)  EXPOSE 80                     0B        
<missing>      23 months ago        /bin/sh -c #(nop)  ENTRYPOINT ["/docker-entr…   0B        
<missing>      23 months ago        /bin/sh -c #(nop) COPY file:09a214a3e07c919a…   4.61kB    
<missing>      23 months ago        /bin/sh -c #(nop) COPY file:0fd5fca330dcd6a7…   1.04kB    
<missing>      23 months ago        /bin/sh -c #(nop) COPY file:0b866ff3fc1ef5b0…   1.96kB    
<missing>      23 months ago        /bin/sh -c #(nop) COPY file:65504f71f5855ca0…   1.2kB     
<missing>      23 months ago        /bin/sh -c set -x     && addgroup --system -…   61.1MB    
<missing>      23 months ago        /bin/sh -c #(nop)  ENV PKG_RELEASE=1~bullseye    0B        
<missing>      23 months ago        /bin/sh -c #(nop)  ENV NJS_VERSION=0.7.1         0B        
<missing>      23 months ago        /bin/sh -c #(nop)  ENV NGINX_VERSION=1.21.5      0B        
<missing>      23 months ago        /bin/sh -c #(nop)  LABEL maintainer=NGINX Do…   0B        
<missing>      23 months ago        /bin/sh -c #(nop)  CMD ["bash"]                  0B        
<missing>      23 months ago        /bin/sh -c #(nop) ADD file:09675d11695f65c55…   80.4MB    
[root@docker ~]# 

新的镜像定制好后,可以运行这个镜像。

[root@docker ~]# docker run --name web2 -d -p 81:80 nginx:v2
4ceaadbc86154c3a4a04b87b1c43ab4f6fbdc1fd9b3419f75b689aed37ef66d4

在这里插入图片描述
这里我们命名新的服务为web2,并且映射到81端口。访问http://localhost:81查看页面结果,其内容应该和之前修改后的webserver一样。
至此,我们第一次完成了定制镜像,使用的是docker commit命令,手动操作给旧的镜像添加了新的一层,形成新的镜像。现在,我们对镜像多层存储应该有了更直观的感受。
但是,docker commit仍然需要慎用。使用docker commit命令虽然可以比较直观地帮助理解镜像分层存储的概念,但是实际环境中并不会这样使用。
首先,如果仔细观察之前的docker diff webserver的结果,会发现除了真正想要修改的/usr/share/nginx/html/index.html文件外,由于命令的执行,还有很多文件被改动或添加了。这还仅仅是最简单的操作,如果是安装软件包、编译构建,那么会有大量的无关内容被添加进来,将会导致镜像极为臃肿。
此外,使用docker commit意味着所有对镜像的操作都是黑箱操作,生成的镜像也被称为黑箱镜像,换句话说,就是除了制作镜像的人知道执行过什么命令、怎么生成的镜像外,别人根本无从得知。而且,即使是这个制作镜像的人,过一段时间后也无法记清具体的操作。这种黑箱镜像的维护工作是非常痛苦的。
另外,回顾之前提及的镜像所使用的分层存储的概念,除当前层外,之前的每一层都是不会发生改变的。换句话说,任何修改的结果仅仅是在当前层进行标记、添加、修改,而不会改动上一层。如果使用docker commit制作镜像,后期修改的话,每一次修改都会让镜像更加臃肿,所删除的上一层的东西并不会丢失,会一直如影随形地跟着这个镜像,即使根本无法访问到,也会让镜像更加臃肿。

使用docker build命令+Dockerfile文件定制镜像

镜像的定制实际上就是定制每一层所要添加的配置、文件。如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,那么之前提及的无法重复的问题、镜像构建透明性的问题、体积的问题就都迎刃而解了。这个脚本就是Dockerfile。
Dockerfile是一个文本文件,其内容包含了一条条的指令,每一条指令构建一层,因此每一条指令的内容就是描述该层应当如何构建。
以下举例说明如何使用Dockerfile来定制nginx镜像。首先在一个空白目录中建立一个文本文件,并命名为Dockerfile:

[root@docker ~]# mkdir mynginx
[root@docker ~]# cd mynginx/
[root@docker mynginx]# touch Dockerfile
[root@docker mynginx]# 

其内容为:

FROM nginx
RUN echo ¹<h1>Hello,Docker!</hl>¹>/usr/share/nginx/html/index.html

这个Dockerfile很简单,一共就两行,涉及两条指令:FROM和RUN。FROM指令是最重要的一个指令,且必须为Dockerfile文件开篇的第一个非注释行,用于为镜像文件构建过程指定基础镜像,后续的指令运行于此基础镜像提供的运行环境中。定制的镜像都是基于FROM的镜像,这里的nginx就是定制需要的基础镜像。后续的操作都是基于nginx。RUN指令用于执行后面跟着的命令行命令。
编写完Dockerfile文件后,开始构建镜像。在Dockerfile文件的存放目录下使用docker build命令执行构建命令。例如:

[root@docker mynginx]# docker build -t nginx:v3 .
[+] Building 0.6s (6/6) FINISHED                                                             docker:default=> [internal] load .dockerignore                                                                      0.0s=> => transferring context: 2B                                                                        0.0s=> [internal] load build definition from Dockerfile                                                   0.0s=> => transferring dockerfile: 177B                                                                   0.0s=> [internal] load metadata for docker.io/library/nginx:latest                                        0.0s=> [1/2] FROM docker.io/library/nginx                                                                 0.0s=> [2/2] RUN echo '<h1>Hello,Docker!</hl>' > /usr/share/nginx/html/index.html                         0.4s=> exporting to image                                                                                 0.0s=> => exporting layers                                                                                0.0s=> => writing image sha256:cc54c98400c7db4200160baf22e838488239e8a463b3c925e74f97a4c6f1a88e           0.0s=> => naming to docker.io/library/nginx:v3                                                            0.0s
[root@docker mynginx]# 

最后的“.”代表本次执行的上下文路径。上下文路径是指Docker在构建镜像时要使用本机的文件(比如复制),docker build命令得知这个路径后,会将路径下的所有内容打包。
除了标准地使用Dockerfile生成镜像的方法外,由于各种特殊需求和历史原因,还提供了一些其他方法用以生成镜像。例如从rootfs压缩包导入,命令格式如下:

docker import [选项] <文件>|<URL>|-[<仓库名>[:<标签>]]

压缩包可以是本地文件、远程Web文件,甚至是从标准输入中得到的。压缩包将会在镜像/目录展开,并直接作为镜像第一层提交。
使用docker save命令可以将镜像保存为归档文件,保存镜像的命令为:

[root@docker mynginx]# docker save nginx:v3 -o nginxv3
[root@docker mynginx]# file nginxv3
nginxv3: POSIX tar archive
[root@docker mynginx]# 

注意,如果同名则会覆盖(没有警告)。
使用gzip压缩:

[root@docker mynginx]# docker save nginx:v3 | gzip> nginx-v3.tar.gz
[root@docker mynginx]# ls -l |grep 'nginx'
-rw-------. 1 root root 145911808 129 16:17 nginxv3
-rw-r--r--. 1 root root  54826265 129 16:18 nginx-v3.tar.gz
[root@docker mynginx]# 

然后将nginx-v3.tar.gz文件复制到另一个机器上,用下面这个命令加载镜像:
s docker load -i nginx-v3.tar.gz
Loaded image:nginx:v3
如果结合这两个命令以及ssh甚至pv的话,利用Linux强大的管道,我们可以写一个命令完成将镜像从一个机器迁移到另一个机器,并且带进度条功能:

docker save <镜像名> | bzip2 | pv |ssh <用户名>@<主机名> 'cat | docker load'

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

黑豹程序员-java发邮件,发送内容支持html,带多附件的案例

介绍 发邮件mail是常见的软件功能&#xff0c;下面利于spring和java的mail库实现发送内容支持html&#xff0c;带多附件的案例 开启SMTP邮件发送协议 谁提供的SMTP邮件服务&#xff0c;就找谁开启。QQ邮箱类似。 依赖 <!--Java MAil 发送邮件API--><dependency&g…

GPT-4V 在机器人领域的应用

在科技的浩渺宇宙中&#xff0c;OpenAI如一颗璀璨的星辰&#xff0c;于2023年9月25日&#xff0c;以一种全新的方式&#xff0c;向世界揭示了其最新的人工智能力作——GPT-4V模型。这次升级&#xff0c;为其旗下的聊天机器人ChatGPT装配了语音和图像的新功能&#xff0c;使得用…

Linux基本指令(超详版)

Linux基本指令&#xff08;超详版&#xff09; 1. ls指令2.pwd指令3. cd 指令4.touch指令5mkdir指令6.rmdir指令&&rm指令7.man指令7.cp指令8.mv指令9.echo指令10.cat指令11.more指令12.less指令13.head指令14.tail指令15.date指令16.find指令17.grep指令zip(打包压缩) …

Spring基于XML文件配置AOP

AOP AOP&#xff0c;面向切面编程&#xff0c;是对面向对象编程OOP的升华。OOP是纵向对一个事物的抽象&#xff0c;一个对象包括静态的属性信息&#xff0c;包括动态的方法信息等。而AOP是横向的对不同事物的抽象&#xff0c;属性与属性、方法与方法、对象与对象都可以组成一个…

kafka常见问题处理

1. 如何防⽌消息丢失 在生产者层面&#xff0c;我们有个ack参数确认机制 设置成-1&#xff0c;也就是副本全部同步了leader才发送ack&#xff0c;这样确保leader和副本挂掉只剩一个还能 保证消息不丢失 消费者&#xff1a; 把⾃动提交改成⼿动提交 2. 如何防⽌重复消费 在…

飞天使-linux操作的一些技巧与知识点3

http工作原理 http1.0 协议 使用的是短连接&#xff0c;建立一次tcp连接&#xff0c;发起一次http的请求&#xff0c;结束&#xff0c;tcp断开 http1.1 协议使用的是长连接&#xff0c;建立一次tcp的连接&#xff0c;发起多次http的请求&#xff0c;结束&#xff0c;tcp断开ngi…

【小米电脑管家】安装使用教程--非小米电脑

安装说明功能体验下载资源 Xiaomi HyperOS发布后&#xff0c;小米妙享电脑端独立版本也走向终点&#xff0c;最新的【小米电脑管家】将会内置妙享实现万物互联。那么本篇文章将分享非小米电脑用户如何绕过设备识别验证安装使用【小米电脑管家】实现万物互联 安装说明 1.解压文…

【探索Linux】—— 强大的命令行工具 P.21(多线程 | 线程同步 | 条件变量 | 线程安全)

阅读导航 引言一、线程同步1. 竞态条件的概念2. 线程同步的概念 二、条件变量1. 条件变量函数⭕使用前提&#xff08;1&#xff09;初始化条件变量&#xff08;2&#xff09;等待条件满足&#xff08;3&#xff09;唤醒等待pthread_cond_broadcast()pthread_cond_signal() &…

windows安装protoc、protoc-gen-go、protoc-gen-go-grpc

文章目录 一、 protoc二、protoc-gen-go三、protoc-gen-go-grpc 一、 protoc 1&#xff0c;下载&#xff1a;https://github.com/google/protobuf/releases 下载对应的protoc&#xff0c;注意选择windows 2&#xff0c;下好之后解压就行&#xff0c;然后把bin目录加入到环境…

JAVA多线程

线程是相当于独立的&#xff0c;在线程中的也是句不变量&#xff0c;除非i将变量定义一在类中或者调用其他类中的方法&#xff0c;来实现公用。 多线程的创建&#xff1a;有两种方案进行创建多线程 Thread对象提供的多线程(无返回值结果void)&#xff1a; main方法默认是一条主…

【出现模块node_modules里面包找不到】

#pic_center R 1 R_1 R1​ R 2 R^2 R2 目录 一、出现的问题二、解决办法三、其它可供参考 一、出现的问题 在本地运行 npm run docs:dev之后&#xff0c;出现 Error [ERR_MODULE_NOT_FOUND]: Cannot find package Z:\Blog\docs\node_modules\htmlparser2\ imported from Z:\Blo…

坚鹏:中国建设银行商业银行场景生态搭建与GBC联动培训

中国建设银行股份有限公司是一家中国领先的大型商业银行&#xff0c;总部设在北京&#xff0c;其前身中国人民建设银行成立于1954年10月。2005年10月在香港联合交易所挂牌上市&#xff0c;2007年9月在上海证券交易所挂牌上市。建设银行为客户提供公司金融业务、个人金融业务、资…

【MATLAB】基于EMD分解的信号去噪算法(基础版)

代码操作 【MATLAB】基于EMD分解的信号去噪算法&#xff08;基础版&#xff09; 代码的主要内容 基于EMD&#xff08;经验模态分解&#xff09;的信号去噪算法通常可以结合相关系数、信号的熵值或者方差贡献率来完成去噪处理。这些指标可以用于确定阈值&#xff0c;从而对信号…

MVC、MVP、MVVM模式的区别

前言&#xff1a;这三个表现层框架设计模式是依次进化而形成MVC—>MVP—>MVVM。在以前传统的开发模式当中即MVC模式&#xff0c;前端人员只负责Model&#xff08;数据库&#xff09;、 View&#xff08;视图&#xff09;和 Controller /Presenter/ViewModel&#xff08;控…

地址栏不安全提示

在使用浏览器时访问网站的时候&#xff0c;我们可能会遇到地址栏提示不安全的情况。这种情况通常都是是由于未安装有效SSL证书或者网站SSL证书过期等原因导致的。本文将介绍如何处理地址栏提示不安全的问题&#xff0c;以确保我们的上网安全。 1&#xff0c;缺少SSL证书&#x…

唱响主旋律——建行江门市分行推动服务实体经济高质量发展

建行江门市分行主动对接当地战略部署&#xff0c;在侨乡热土踏歌而行&#xff0c;全力当好服务实体经济的主力军和维护金融稳定的压舱石&#xff0c;在助力再造一个现代化新江门上贡献建行力量。 输血实体 为实体经济服务是金融的天职。建行江门市分行积极发挥在重大基建领域…

[oeasy]python0002_终端_CLI_GUI_编程环境_游戏_真实_元宇宙

回忆 上次 了解了 python 语言的特点 历史悠久功能强大深受好评已成趋势 3大主流操作系统 macwindowslinux 我们 选择 linux 作为基础系统 为什么选择 黑乎乎的命令行界面呢&#xff1f;&#x1f914; GUI vs CLI 个人电脑 用图标和菜单组成 图形界面(GUI) Graphic User I…

tamcat乱码

学习springmvc时tamcat乱码 ①、启动时tomcat控制台乱码 解决方法是&#xff1a;1、先把idea设置里的默认字节码改成utf-8 ​ 2、把idea显示编码改成utf-8&#xff0c;在末尾加上&#xff08; -Dfile.encodingUTF-8&#xff09; ​ 3、最后重启idea 加上这个 -Dfile.encodingU…

异步回调模式

异步回调 所谓异步回调&#xff0c;本质上就是多线程中线程的通信&#xff0c;如今很多业务系统中&#xff0c;某个业务或者功能调用多个外部接口&#xff0c;通常这种调用就是异步的调用。如何得到这些异步调用的结果自然也就很重要了。 Callable、Future、FutureTask publi…

【EI会议征稿中】第三届网络安全、人工智能与数字经济国际学术会议(CSAIDE 2024)

第三届网络安全、人工智能与数字经济国际学术会议&#xff08;CSAIDE 2024&#xff09; 2024 3rd International Conference on Cyber Security, Artificial Intelligence and Digital Economy 第二届网络安全、人工智能与数字经济国际学术会议&#xff08;CSAIDE 2023&…