当前位置: 首页 > news >正文

CompletableFuture详解

1、概述

咱们都知道可以通过继承Thread类或者实现Runnable接口两种方式实现多线程。但是有时候我们希望得到多线程异步任务执行后的结果,也就是异步任务执行后有返回值,Thread和Runnable是不能实现的。当我们需要返回值的时候怎么办呢? Java 1.5 推出的Callable和Future接口就解决了这个问题。但是因为Future有几个局限,由于这几个局限,在Java1.8就推出了加强版的Future类:CompletableFuture。本篇文章我们通过实际需求、实例代码分析Future缺陷讲解CompletableFuture的设计原理。

2、Future使用

假如我们现在有如下需求:

老板正在开会,开会过程中发现少一份材料,通知秘书去整理,在秘书整理过程中老板这边还在继续开会,秘书整理完以后将材料给到老板手中。

需求分析:

老板开会是主线程,不能中断。

秘书就是异步任务

秘书执行完任务需要将结果返回给老板这个主线程手中。

咱们看看通过Future实现此需求有什么局限,然后再通过CompletableFuture实现此需求看看是否更好。

Future接口(实现类:FutureTask)定义了操作异步任务执行的一些方法:如获取异步任务执行结果、取消任务的执行结果、判断任务是否被取消、判断任务执行是否完成等。

 实现老板开会,秘书整理材料需求方式一代码:

package com.lc;import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;/*** 老板开会Future实现** @author liuchao* @date 2023/4/5*/
public class BossMeeting {/*** 主线程为老板正在开会** @param args*/public static void main(String[] args) {System.out.println("老板开会start");ExecutorService executorService = Executors.newFixedThreadPool(1);FutureTask<String> secretaryFuture = new FutureTask<>(() -> {Thread.sleep(1000);return "老板需要的材料";});//老板发现缺少材料,提交异步任务(找秘书)executorService.submit(secretaryFuture);/*** 方法1* 局限:导致线程堵塞*/try {//获取秘书搜集的材料 (堵塞线程)String material = secretaryFuture.get();System.out.println("秘书搜集到的材料:" + material);} catch (InterruptedException e) {throw new RuntimeException(e);} catch (ExecutionException e) {throw new RuntimeException(e);}/*** 方法2* 通过while轮询方式会消耗cpu*/while (true) {if (secretaryFuture.isDone()) {try {//获取秘书搜集的材料 (堵塞线程)String material = secretaryFuture.get();System.out.println("秘书搜集到的材料:" + material);break;} catch (InterruptedException e) {throw new RuntimeException(e);} catch (ExecutionException e) {throw new RuntimeException(e);}} else {try {Thread.sleep(500);} catch (InterruptedException e) {throw new RuntimeException(e);}}}System.out.println("老板开会end");}
}

实例代码提供了两种方式获取秘书搜集到的材料,都是有局限性并且堵塞了主线程。

通过现实需求分析,老板开会能一直等着秘书将材料整理完再继续吗,显然是不行的。

现实情况是秘书(异步任务)执行完任务后,主动告知老板(主线程)。

Future使用局限性汇总:

  • Future的get方法会导致主线程阻塞
  • 轮询获取结果会消耗cpu资源
  • 多个Future任务不能按照顺序执行
  • Future Api无异常处理

3、CompletableFuture实现

CompletableFuture提供了一种观察者模式类似的机制,可以让任务执行完成后通知监听的一方。

首先看看CompletableFuture的类图关系,CompletableFuture实现了Future和CompletionStage接口,因此看来CompletableFuture具有Future和CompletionStage的特性。

public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {

 CompletionStage接口拥有的API

 咱们看看通过CompletableFuture实现的老板开会需求代码实例如下:

package com.lc;import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** 老板开会Future实现** @author liuchao* @date 2023/4/5*/
public class BossMeeting {/*** 主线程为老板正在开会** @param args*/public static void main(String[] args) {System.out.println("老板开会start");ExecutorService executorService = Executors.newFixedThreadPool(1);try {CompletableFuture.supplyAsync(() -> {try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}return "秘书搜集完材料";//结束返回}, executorService).whenComplete((v, e) -> {//无异常说明 执行成功if (e == null) {System.out.println("秘书搜集到的材料:" + v);}//异常处理}).exceptionally(e -> {e.printStackTrace();System.out.println("执行异常:" + e.getCause());return null;});System.out.println("老板继续开会");try {//模拟老板继续开会3秒钟Thread.sleep(3000);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("老板开会end");} finally {executorService.shutdown();}}
}

执行结果:发现没有任何堵塞,任务提交主线程继续执行,异步任务执行完成主动告知主线程

老板开会start
老板继续开会
秘书搜集到的材料:秘书搜集完材料
老板开会end 

4、CompletableFuture Api详解

4.1、CompletableFuture创建方式

官方推荐使用CompletableFuture提供的静态方法创建CompletableFuture实例,以下是提供的静态方法:

// 无返回值 使用ForkJoinPool线程池
public static CompletableFuture<Void> runAsync(Runnable runnable)
// 无返回值 可以自定义线程池
public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor)
// 有返回值 使用ForkJoinPool线程池
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)
// 有返回值 可以自定义线程池
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor)

supply开头:这种方法,可以返回异步线程执行之后的结果。
run开头:这种不会返回结果,就只是执行线程任务。
如果你想异步运行一些后台任务并且不想从任务中返回任何东西,那么你可以使用run开头的

实例:

package com.lc;import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** @author liuchao* @date 2023/4/5*/
public class Test {public static void main(String[] args) {//无返回结果CompletableFuture.runAsync(() -> {System.out.println("无返回值线程:" + Thread.currentThread().getName());System.out.println("执行异步任务,无返回结果");});//无返回值 自定义线程ExecutorService executors = Executors.newFixedThreadPool(2);CompletableFuture.runAsync(() -> {System.out.println("无返回值,自定义线程:" + Thread.currentThread().getName());System.out.println("执行异步任务,无返回自定义线程结果");}, executors);//有返回结果CompletableFuture.supplyAsync(() -> {System.out.println("执行异步任务,有返回值");System.out.println("有返回值线程:" + Thread.currentThread().getName());return "返回值";});//有返回结果自定义线程CompletableFuture.supplyAsync(() -> {System.out.println("执行异步任务,有返回值");System.out.println("有返回值线程:" + Thread.currentThread().getName());return "返回值";}, executors);}
}

 执行效果:

无返回值线程:ForkJoinPool.commonPool-worker-1
执行异步任务,无返回结果
无返回值,自定义线程:pool-1-thread-1
执行异步任务,无返回自定义线程结果
执行异步任务,有返回值
有返回值线程:ForkJoinPool.commonPool-worker-1
执行异步任务,有返回值
有返回值线程:pool-1-thread-2
 

4.2、CompletableFuture获取返回值

通过get、join、getNow获取返回值,区别如下:

  • join:返回结果或者抛出一个unchecked异常(CompletionException),不需要显示捕获异常。
  • get:返回结果或者一个具体的异常(ExecutionException, InterruptedException),此方法继承至Future是堵塞的。
  • getNow:如果当前任务执行完成,返回执行结果,否则返回valueIfAbsent(默认值)。

实例:

/*** 通过get获取方法*/public void test1() {CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "get方法需要显示捕获异常");try {System.out.println(future.get());} catch (InterruptedException e) {throw new RuntimeException(e);} catch (ExecutionException e) {throw new RuntimeException(e);}}/*** join 不需要显示捕获异常*/public void test2() {CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "join方法不需要显示捕获异常");System.out.println(future.join());}/*** getNow方法可以设置默认值* 在有效的时间内,未返回结果,则直接返回默认值*/public void test3() {CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "getNow获取返回值");System.out.println(future.getNow("默认值"));}

4.3、其他Api详解

  • thenApply():拿到上一个异步执行的结果继续后续操作

实例:

        // 模拟 1 + 1 + 1CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> 1).thenApply(v -> v + 1).thenApply(v -> v + 1);System.out.println("执行结果:" + future.getNow(-1));

返回结果:3

thenApply()是线程的后续操作,可以拿到上一次线程执行的返回结果作为本次thenApply()的参数一直传递下去。 并且是有返回结果的。

  • thenAccept() 和 thenRun()方法

如果你不想从你的回调函数中返回任何东西,只想在 Future 完成后运行一些代码,那么你可以使用thenAccept()andthenRun()方法。这些方法是消费者Consumer<? super T> action,通常用作回调链中的最后一个回调。

实例:

        // 模拟 1 + 1 + 1CompletableFuture.supplyAsync(() -> 1).thenApply(v -> v + 1).thenApply(v -> v + 1).thenAccept(r -> System.out.println("1+1+1=" + r));

结果:1+1+1=3

  • complete():当前阶段异步任务执行完成

complete()其实也是个消费操作,但是与thenRun()不同的是,里面可以可抛出的异常

// 区别就是不是异步处理
public CompletableFuture<T>  whenComplete(BiConsumer<? super T,? super Throwable> action)
// 使用异步处理
public CompletableFuture<T>  whenCompleteAsync(BiConsumer<? super T,? super Throwable> action)
// 区别在于可以指定线程池
public CompletableFuture<T>  whenCompleteAsync(BiConsumer<? super T,? super Throwable> action, Executor executor)
// 接收一个可抛出的异常,且必须有返回值
public CompletableFuture<T>  exceptionally(Function<Throwable,? extends T> fn)
  • handle():相比thenApply()抛出异常后还可以继续执行

public <U> CompletableFuture<U> handle(BiFunction<? super T,Throwable,? extends U> fn)
public <U> CompletableFuture<U> handleAsync(BiFunction<? super T,Throwable,? extends U> fn)
public <U> CompletableFuture<U> handleAsync(BiFunction<? super T,Throwable,? extends U> fn, Executor executor)

handle方法集和上面的complete方法集没有区别,同样有两个参数一个返回结果和可抛出异常,区别就在于返回值

5、CompletableFuture综合使用

需求:要查找10个订单信息以及关联的商品、图片信息

订单上有商品ID,通过商品ID可以查询到商品详细信息,图片信息存储在商品详细信息中。

那就需要查询完订单再查询商品最后查询图片信息,这3个异步任务需要串行执行。

实例代码:

package com.lc;import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;/*** @author liuchao* @date 2023/4/5*/
public class Test {public static void main(String[] args) {//10个订单号List<String> orderCodeList = Arrays.asList(new String[]{"order_01", "order_02", "order_03", "order_04","order_05", "order_06", "order_07", "order_08", "order_09", "order_10"});//定义线程池ExecutorService threadPool = Executors.newFixedThreadPool(15);try {List<String> collect = orderCodeList.stream().map(o ->CompletableFuture.supplyAsync(() -> String.format("订单:%s,关联商品ID为:%s", o, ThreadLocalRandom.current().nextInt()), threadPool).thenApplyAsync((v) -> String.format(v + ",关联图片ID为:%s", ThreadLocalRandom.current().nextInt()), threadPool).thenApplyAsync((v) -> String.format(v + ",关联图信息获取成功"), threadPool).exceptionally(e -> {e.printStackTrace();return null;}).join()).collect(Collectors.toList());//打印结果System.out.println(collect);} finally {//释放资源threadPool.shutdown();}}
}

相关文章:

CompletableFuture详解

1、概述 咱们都知道可以通过继承Thread类或者实现Runnable接口两种方式实现多线程。但是有时候我们希望得到多线程异步任务执行后的结果&#xff0c;也就是异步任务执行后有返回值&#xff0c;Thread和Runnable是不能实现的。当我们需要返回值的时候怎么办呢&#xff1f; Java…...

(学习日记)2023.3.10

写在前面&#xff1a; 由于时间的不足与学习的碎片化&#xff0c;写博客变得有些奢侈。 但是对于记录学习&#xff08;忘了以后能快速复习&#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位&#xff0c;以时间为顺序&#xff0c;仅仅将博客当做一个知识学习的目录&a…...

【图像分割】Meta分割一切(SAM)模型环境配置和使用教程

注意&#xff1a;python>3.8, pytorch>1.7,torchvision>0.8 Feel free to ask any question. 遇到问题欢迎评论区讨论. 官方教程&#xff1a; https://github.com/facebookresearch/segment-anything 1 环境配置 1.1 安装主要库&#xff1a; &#xff08;1&…...

AJ入门路线

一.AspectJ 入门 概述安装示例代码切入点表达式thisJoinPointStaticPart 和 thisJoinPoint与Spring 切面写法的对比总结 初步了解了aspectJ的使用&#xff0c;我们可以了解以下几点&#xff1a; 1&#xff09;aspectJ的使用是在编译期&#xff0c;通过特殊的编译器可以在不改变…...

多商户商城小程序源码开发需具备哪些功能?

随着电商的进一步发展&#xff0c;传统企业为了更好的占领市场也纷纷向电商市场迈进&#xff0c;着手打造属于自己的商城系统。多商户商城系统是一种多商户、多商品、多支付的电子商务平台&#xff0c;功能丰富&#xff0c;涵盖多个行业&#xff0c;能够满足多种商家和用户的需…...

【动态规划模板】最长公共|上升子序列问题

最长公共子序列&#x1f349; 给定两个长度分别为N和M的字符串A和B&#xff0c;求既是A的子序列又是B的子序列的字符串长度最长是多少。 输入格式 第一行包含两个整数 N 和 M。 第二行包含一个长度为N的字符串&#xff0c;表示字符串A。 第三行包含一个长度为M的字符串&am…...

Android系统启动流程--zygote进程的启动流程

在上一篇init进程启动流程中已经提到&#xff0c;在init中会解析一个init.rc文件&#xff0c;解析后会执行其中的命令来启动zygote进程、serviceManager进程等&#xff0c;下面我们来看一下&#xff1a; //文件路径&#xff1a;system/core/init/init.cppstatic void LoadBoot…...

C++程序设计——异常

一、C异常概念 异常处理是一种处理错误的方式&#xff0c;当一个函数发现自己无法处理的错误时&#xff0c;就可以抛出异常&#xff0c;让函数的直接或间接的调用者处理这个错误。 &#xff08;1&#xff09;throw&#xff1a;当问题出现时&#xff0c;程序会通过throw关键字抛…...

2022年第十三届蓝桥杯web开发—东奥大抽奖【题目、附官方解答】

冬奥大抽奖 介绍 蓝桥云课庆冬奥需要举行一次抽奖活动&#xff0c;我们一起做一个页面提供给云课冬奥抽奖活动使用。 准备 开始答题前&#xff0c;需要先打开本题的项目代码文件夹&#xff0c;目录结构如下&#xff1a; ├── css │ └── style.css ├── effect.g…...

一份两年前一个月的工作经历没写在简历上,背调前主动坦白,却被背调公司亮了红灯,到手的offer没了!...

只因为简历上漏写了一份一个月的工作&#xff0c;就被亮了背调红灯&#xff0c;这公平吗&#xff1f;一位网友就被狠狠坑了一把&#xff0c;来看下他的遭遇&#xff1a;他有一份两年前、时长一个月的工作经历没写在简历上&#xff0c;背调前主动和背调公司还有招聘方hr都说了这…...

C++游戏分析与破解方法介绍

1、C游戏简介 目前手机游戏直接用C开发的已经不多&#xff0c;使用C开发的多是早期的基于cocos2dx的游戏&#xff0c;因此我们这里就以cocos2d-x为例讲解C游戏的分析与破解方法。 Cocos2d-x是一个移动端游戏开发框架&#xff0c;可以使用C或者lua进行开发&#xff0c;也可以混…...

食堂总是拥挤不堪?解决用餐拥挤,教你一招

随着近几年科技的快速发展&#xff0c;行业里出现了很多新的名词&#xff0c;比如智慧社区、智慧旅游、智慧建筑&#xff0c;那么智慧食堂是什么呢&#xff1f;它又是如何实现全自助、全智能消费&#xff1f; 在先进的智能技术以及市场需求带动下&#xff0c;智慧食堂经历了由传…...

ubuntu系统安装时 MBR和GPT的区别

主引导记录&#xff08;Master Boot Record &#xff0c; MBR&#xff09;是指一个存储设备的开头 512 字节。它包含操作系统的引导器和存储设备的分区表。   全局唯一标识分区表&#xff08;GUID Partition Table&#xff0c;缩写&#xff1a;GPT&#xff09;是一个实体硬盘…...

我在windows10下,使用msys64 mingw64终端

系列文章目录 文章目录系列文章目录前言一、MSYS2是什么&#xff1f;前言 msys2官网 MSYS2 &#xff08;Minimal SYStem 2&#xff09; 是一个MSYS的独立改写版本&#xff0c;主要用于 shell 命令行开发环境。 同时它也是一个在Cygwin &#xff08;POSIX 兼容性层&#xff09…...

个人2023FALL CS申请总结(PhD/MPhil/保研夏令营)

个人2023FALL CS申请总结&#xff08;PhD/MPhil/保研夏令营&#xff09;写在最前个人BG及申请情况个人BG申请情况MPhilPhD收获一句话总结&#xff1a;心态爆炸没用&#xff0c;脸皮够厚够勇就行 写在最前 真是一场恶战。有几天&#xff0c;我每天早上都海投几封套瓷邮件&…...

【优化算法】使用遗传算法优化MLP神经网络参数(TensorFlow2)

文章目录任务查看当前的准确率情况使用遗传算法进行优化完整代码任务 使用启发式优化算法遗传算法对多层感知机中中间层神经个数进行优化&#xff0c;以提高模型的准确率。 待优化的模型&#xff1a; 基于TensorFlow2实现的Mnist手写数字识别多层感知机MLP # MLP手写数字识别…...

CAM类激活映射 |神经网络可视化 | 热力图

文章目录前言&#xff1a;安装库&#xff1a;分类案例--ResNet50分割案例AttributeError: ‘tuple‘ object has no attribute ‘cpu‘RuntimeError: grad can be implicitly created only for scalar outputsTypeError: cant convert cuda:0 device type tensor to numpy. Use…...

RecyclerView+BaseRecyclerViewAdapterHelper显示不全只显示第一行item的解决问题

RecyclerViewBaseRecyclerViewAdapterHelper显示不全只显示第一行item&#xff0c;我懵了…&#xff0c;我不说多&#xff0c;直接说吧 先看一下适配器代码中的convert()方法&#xff1a; class MineRadioAdapter(layoutResId: Int R.layout.item_my_live) :BaseQuickAdapte…...

解决后端无法对前端的ajax请求重定向

本章目录&#xff1a; 问题描述 AJAX请求后端直接重定向失败解决方案 后端拦截请为响应头添加重定向标志后端拦截器为响应头添加重定向路径前端响应拦截器获取响应头数据&#xff0c;并通过location.href url 完成页面跳转一、问题描述 本来想在拦截器里设置未登录用户访问指…...

【Python】1分钟就能制作精美的框架图?太棒啦

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录前言一、准备二、基本使用与例子1.初始化与导出2.节点类型3.集群块4.自定义线的颜色与属性总结前言 Diagrams 是一个基于Python绘制云系统架构的模块&#xff0c;它能…...

淘宝必备的补单技巧及注意事项!

补单&#xff0c;是优化善后的s单。单只是模拟用户的购物习惯&#xff0c;而补单同时还要模拟整个店铺的综合数据&#xff0c;包括点击率、转化率等等&#xff0c;补到略高于同行、竞品的平均数据时&#xff0c;淘宝会判断为买家比较喜欢你的商品&#xff0c;从而给你更多推荐机…...

【实用篇】SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式,系统详解springcloud分布式

文章目录一、服务拆分1.1 服务拆分Demo1.2 微服务远程调用二、Eureka2.1 Eureka原理2.2 Eureka-server服务搭建2.3 eureka-client服务注册2.4 eureka-client服务复制2.5 eureka服务发现三、Ribbon负载均衡3.1 负载均衡原理3.2 负载均衡策略3.3 自定义负载均衡策略3.4 饥饿加载与…...

私人飞机、公务机包机会成为富豪圈的主流出行方式吗?

从炫耀性消费到按需使用&#xff0c;私人飞机的消费群体正在被拓宽&#xff0c;但离“成为主流”还有一段距离。“时间就是金钱”为有钱人消费私人飞机提供合理动机&#xff0c;而这群高净值人群的数量增长则成为撑起市场基本面。据相关数据显示&#xff0c;2018年全球超级富豪…...

Oracle组织架构

组织架构 &#xff08;一&#xff09;业务组&#xff08;BG&#xff09; &#xff08;二&#xff09;法律实体&#xff08;LE&#xff09; &#xff08;三&#xff09;业务实体&#xff08;OU&#xff09; &#xff08;四&#xff09;库存组织&#xff08;INV&#xff09; …...

最小公倍数

目录 最小公倍数 程序设计 程序分析 最小公倍数 【问题描述】给定两个正整数,计算这两个数的最小公倍数。 【输入形式】输入包含多组测试数据,每组只有一行,包括两个不大于1000的正整数. 【输出形式】 对于每个测试用例,给出这两个数的最小公倍数,每个实例输出一行。…...

二叉树的后序遍历(力扣145)

目录 题目描述&#xff1a; 解法一&#xff1a;递归法 解法二&#xff1a;迭代法 解法三&#xff1a;Morris遍历 二叉树的后序遍历 题目描述&#xff1a; 给你一棵二叉树的根节点 root &#xff0c;返回其节点值的 后序遍历 。 示例 1&#xff1a; 输入&#xff1a;root …...

《Effective C++》读书纪实 -- 诸君同享

文章目录《Effective C》是一本经典的C编程指南&#xff0c;共包含50条C编程的最佳实践。 确定你的构造函数的行为 在构造函数中&#xff0c;应该尽可能地避免调用虚函数、非静态成员函数和虚基类的函数。 尽量使用const、enum、inline替换#define 使用const、enum、inline可以…...

【云原生】K8S-ConfigMap 实现应用和配置分离

文章目录前言ConfigMap 背景ConfigMap 创建方式ConfigMap 的使用使用 ConfigMap 的注意事项总结前言 Kubernetes 是目前最流行的容器编排系统之一&#xff0c;它提供了丰富的功能来支持容器化应用程序的管理和部署。 ConfigMap 是 Kubernetes 中重要的资源对象&#xff0c;用…...

java -测距工具(经纬度)

代码 /*** 测距工具* author qb*/ public class DistanceUtils {/*** 赤道半径*/private static final double EARTH_RADIUS 6378.137;private static double rad(double d) {return d * Math.PI / 180.0;}/*** Description : 通过经纬度获取距离(单位&#xff1a;米)* Group…...

postgres分区表的创建-基于继承

参考文档&#xff1a; http://postgres.cn/docs/12/ddl-partitioning.html 创建基于继承的分区表的步骤 1 创建父表 2 创建子表&#xff0c;从父表继承过来 3 创建函数及触发器&#xff0c;使插入的数据根据规则&#xff0c;插入到对应的子表中 -- 创建父表 CREATE TABLE a…...

ps如何做网站横幅/潍坊seo教程

求平均成绩 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 79662 Accepted Submission(s): 19180Problem Description假设一个班有n(n<50)个学生&#xff0c;每人考m(m<5)门课&#xff0c;求每个学生的…...

wordpress程序版本/怎么推广游戏代理赚钱

文章目录0 效果1 实现1.1 创建名称和位置1.2 关联信号和槽函数1.3 编写事件0 效果 开始&#xff1a; 中间步骤 结束&#xff1a; 1 实现 1.1 创建名称和位置 在ui设计界面新建需要的菜单名称 1.2 关联信号和槽函数 找到对象的名称 在类的构造函数中编写函数&#x…...

广州云脑网站建设/媒体吧软文平台

效果&#xff1a; 代码&#xff1a; 第一步&#xff1a;页面底部放两个浮动层&#xff0c;让指向图标不透明&#xff1a; <div class"share" style"display:none;filter:alpha(Opacity30);-moz-opacity:0.9;opacity: 0.5;width:100%;height:90%; background:…...

wordpress 淘宝/cba目前排名

今天IIS出了问题,怎么弄都不能显示asp页面,htm文件倒是可以显示,结果网上搜索了许多所谓"解决方案",最后以把我的IIS彻底搞得卸也卸不掉,重装也装不上去的境地,安装和卸载时老是提示:文件复制被取消,安装程序无法继续. 最终靠强制手工卸载IIS6而搞定: 原文如下: 1、把…...

做外贸一般用哪些网站好/饥饿营销案例

这两年少儿编程教育如火如荼&#xff0c;科技和政策的推动让家长越来越意识到编程的重要性。随着人工智能的发展和应用深入&#xff0c;编程也慢慢将成为每一个孩子的必备基础技能。但与此同时&#xff0c;也有很多国内家长对少儿编程这个词比较陌生&#xff0c;很多家长对少儿…...

wordpress b/s分离/制作网站的软件叫什么

目录 一、图标icon 二、进度条progress 三、文本text 四、富文本rich-text 一、图标icon 属性类型默认值必填说明typestring 是icon的类型&#xff0c;有效值&#xff1a;success, success_no_circle, info, warn, waiting, cancel, download, search, clearsizenumber/st…...