Java并发包--线程池框架

转载请注明出处:http://www.cnblogs.com/skywang12345/p/3509903.html

 

线程池架构图

线程池的架构图如下:

 

 

1. Executor

它是"执行者"接口,它是来执行任务的。准确的说,Executor提供了execute()接口来执行已提交的 Runnable 任务的对象。Executor存在的目的是提供一种将"任务提交"与"任务如何运行"分离开来的机制。
它只包含一个函数接口:

void execute(Runnable command)

 

2. ExecutorService

ExecutorService继承于Executor。它是"执行者服务"接口,它是为"执行者接口Executor"服务而存在的;准确的话,ExecutorService提供了"将任务提交给执行者的接口(submit方法)","让执行者执行任务(invokeAll, invokeAny方法)"的接口等等。

ExecutorService的函数列表

复制代码
 1 // 请求关闭、发生超时或者当前线程中断,无论哪一个首先发生之后,都将导致阻塞,直到所有任务完成执行。2 boolean awaitTermination(long timeout, TimeUnit unit)3 // 执行给定的任务,当所有任务完成时,返回保持任务状态和结果的 Future 列表。4 <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)5 // 执行给定的任务,当所有任务完成或超时期满时(无论哪个首先发生),返回保持任务状态和结果的 Future 列表。6 <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)7 // 执行给定的任务,如果某个任务已成功完成(也就是未抛出异常),则返回其结果。8 <T> T invokeAny(Collection<? extends Callable<T>> tasks)9 // 执行给定的任务,如果在给定的超时期满前某个任务已成功完成(也就是未抛出异常),则返回其结果。
10 <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
11 // 如果此执行程序已关闭,则返回 true。
12 boolean isShutdown()
13 // 如果关闭后所有任务都已完成,则返回 true。
14 boolean isTerminated()
15 // 启动一次顺序关闭,执行以前提交的任务,但不接受新任务。
16 void shutdown()
17 // 试图停止所有正在执行的活动任务,暂停处理正在等待的任务,并返回等待执行的任务列表。
18 List<Runnable> shutdownNow()
19 // 提交一个返回值的任务用于执行,返回一个表示任务的未决结果的 Future。
20 <T> Future<T> submit(Callable<T> task)
21 // 提交一个 Runnable 任务用于执行,并返回一个表示该任务的 Future。
22 Future<?> submit(Runnable task)
23 // 提交一个 Runnable 任务用于执行,并返回一个表示该任务的 Future。
24 <T> Future<T> submit(Runnable task, T result)
复制代码

 

3. AbstractExecutorService

AbstractExecutorService是一个抽象类,它实现了ExecutorService接口。
AbstractExecutorService存在的目的是为ExecutorService中的函数接口提供了默认实现。

AbstractExecutorService函数列表
由于它的函数列表和ExecutorService一样,这里就不再重复列举了。

 

4. ThreadPoolExecutor

ThreadPoolExecutor就是大名鼎鼎的"线程池"。它继承于AbstractExecutorService抽象类。

ThreadPoolExecutor函数列表

复制代码
 1 // 用给定的初始参数和默认的线程工厂及被拒绝的执行处理程序创建新的 ThreadPoolExecutor。2 ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue)3 // 用给定的初始参数和默认的线程工厂创建新的 ThreadPoolExecutor。4 ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler)5 // 用给定的初始参数和默认被拒绝的执行处理程序创建新的 ThreadPoolExecutor。6 ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory)7 // 用给定的初始参数创建新的 ThreadPoolExecutor。8 ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)9 
10 // 基于完成执行给定 Runnable 所调用的方法。
11 protected void afterExecute(Runnable r, Throwable t)
12 // 如果在保持活动时间内没有任务到达,新任务到达时正在替换(如果需要),则设置控制核心线程是超时还是终止的策略。
13 void allowCoreThreadTimeOut(boolean value)
14 // 如果此池允许核心线程超时和终止,如果在 keepAlive 时间内没有任务到达,新任务到达时正在替换(如果需要),则返回 true。
15 boolean allowsCoreThreadTimeOut()
16 // 请求关闭、发生超时或者当前线程中断,无论哪一个首先发生之后,都将导致阻塞,直到所有任务完成执行。
17 boolean awaitTermination(long timeout, TimeUnit unit)
18 // 在执行给定线程中的给定 Runnable 之前调用的方法。
19 protected void beforeExecute(Thread t, Runnable r)
20 // 在将来某个时间执行给定任务。
21 void execute(Runnable command)
22 // 当不再引用此执行程序时,调用 shutdown。
23 protected void finalize()
24 // 返回主动执行任务的近似线程数。
25 int getActiveCount()
26 // 返回已完成执行的近似任务总数。
27 long getCompletedTaskCount()
28 // 返回核心线程数。
29 int getCorePoolSize()
30 // 返回线程保持活动的时间,该时间就是超过核心池大小的线程可以在终止前保持空闲的时间值。
31 long getKeepAliveTime(TimeUnit unit)
32 // 返回曾经同时位于池中的最大线程数。
33 int getLargestPoolSize()
34 // 返回允许的最大线程数。
35 int getMaximumPoolSize()
36 // 返回池中的当前线程数。
37 int getPoolSize()
38 // 返回此执行程序使用的任务队列。
39 BlockingQueue<Runnable> getQueue()
40 // 返回用于未执行任务的当前处理程序。
41 RejectedExecutionHandler getRejectedExecutionHandler()
42 // 返回曾计划执行的近似任务总数。
43 long getTaskCount()
44 // 返回用于创建新线程的线程工厂。
45 ThreadFactory getThreadFactory()
46 // 如果此执行程序已关闭,则返回 true。
47 boolean isShutdown()
48 // 如果关闭后所有任务都已完成,则返回 true。
49 boolean isTerminated()
50 // 如果此执行程序处于在 shutdown 或 shutdownNow 之后正在终止但尚未完全终止的过程中,则返回 true。
51 boolean isTerminating()
52 // 启动所有核心线程,使其处于等待工作的空闲状态。
53 int prestartAllCoreThreads()
54 // 启动核心线程,使其处于等待工作的空闲状态。
55 boolean prestartCoreThread()
56 // 尝试从工作队列移除所有已取消的 Future 任务。
57 void purge()
58 // 从执行程序的内部队列中移除此任务(如果存在),从而如果尚未开始,则其不再运行。
59 boolean remove(Runnable task)
60 // 设置核心线程数。
61 void setCorePoolSize(int corePoolSize)
62 // 设置线程在终止前可以保持空闲的时间限制。
63 void setKeepAliveTime(long time, TimeUnit unit)
64 // 设置允许的最大线程数。
65 void setMaximumPoolSize(int maximumPoolSize)
66 // 设置用于未执行任务的新处理程序。
67 void setRejectedExecutionHandler(RejectedExecutionHandler handler)
68 // 设置用于创建新线程的线程工厂。
69 void setThreadFactory(ThreadFactory threadFactory)
70 // 按过去执行已提交任务的顺序发起一个有序的关闭,但是不接受新任务。
71 void shutdown()
72 // 尝试停止所有的活动执行任务、暂停等待任务的处理,并返回等待执行的任务列表。
73 List<Runnable> shutdownNow()
74 // 当 Executor 已经终止时调用的方法。
75 protected void terminated()
复制代码

 

5. ScheduledExecutorService

ScheduledExecutorService是一个接口,它继承于于ExecutorService。它相当于提供了"延时"和"周期执行"功能的ExecutorService。
ScheduledExecutorService提供了相应的函数接口,可以安排任务在给定的延迟后执行,也可以让任务周期的执行。

ScheduledExecutorService函数列表

复制代码
1 // 创建并执行在给定延迟后启用的 ScheduledFuture。
2 <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit)
3 // 创建并执行在给定延迟后启用的一次性操作。
4 ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit)
5 // 创建并执行一个在给定初始延迟后首次启用的定期操作,后续操作具有给定的周期;也就是将在 initialDelay 后开始执行,然后在 initialDelay+period 后执行,接着在 initialDelay + 2 * period 后执行,依此类推。
6 ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
7 // 创建并执行一个在给定初始延迟后首次启用的定期操作,随后,在每一次执行终止和下一次执行开始之间都存在给定的延迟。
8 ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit)
复制代码

 

6. ScheduledThreadPoolExecutor

ScheduledThreadPoolExecutor继承于ThreadPoolExecutor,并且实现了ScheduledExecutorService接口。它相当于提供了"延时"和"周期执行"功能的ScheduledExecutorService。
ScheduledThreadPoolExecutor类似于Timer,但是在高并发程序中,ScheduledThreadPoolExecutor的性能要优于Timer。

ScheduledThreadPoolExecutor函数列表

复制代码
 1 // 使用给定核心池大小创建一个新 ScheduledThreadPoolExecutor。2 ScheduledThreadPoolExecutor(int corePoolSize)3 // 使用给定初始参数创建一个新 ScheduledThreadPoolExecutor。4 ScheduledThreadPoolExecutor(int corePoolSize, RejectedExecutionHandler handler)5 // 使用给定的初始参数创建一个新 ScheduledThreadPoolExecutor。6 ScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory)7 // 使用给定初始参数创建一个新 ScheduledThreadPoolExecutor。8 ScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory, RejectedExecutionHandler handler)9 
10 // 修改或替换用于执行 callable 的任务。
11 protected <V> RunnableScheduledFuture<V> decorateTask(Callable<V> callable, RunnableScheduledFuture<V> task)
12 // 修改或替换用于执行 runnable 的任务。
13 protected <V> RunnableScheduledFuture<V> decorateTask(Runnable runnable, RunnableScheduledFuture<V> task)
14 // 使用所要求的零延迟执行命令。
15 void execute(Runnable command)
16 // 获取有关在此执行程序已 shutdown 的情况下、是否继续执行现有定期任务的策略。
17 boolean getContinueExistingPeriodicTasksAfterShutdownPolicy()
18 // 获取有关在此执行程序已 shutdown 的情况下是否继续执行现有延迟任务的策略。
19 boolean getExecuteExistingDelayedTasksAfterShutdownPolicy()
20 // 返回此执行程序使用的任务队列。
21 BlockingQueue<Runnable> getQueue()
22 // 从执行程序的内部队列中移除此任务(如果存在),从而如果尚未开始,则其不再运行。
23 boolean remove(Runnable task)
24 // 创建并执行在给定延迟后启用的 ScheduledFuture。
25 <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit)
26 // 创建并执行在给定延迟后启用的一次性操作。
27 ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit)
28 // 创建并执行一个在给定初始延迟后首次启用的定期操作,后续操作具有给定的周期;也就是将在 initialDelay 后开始执行,然后在 initialDelay+period 后执行,接着在 initialDelay + 2 * period 后执行,依此类推。
29 ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
30 // 创建并执行一个在给定初始延迟后首次启用的定期操作,随后,在每一次执行终止和下一次执行开始之间都存在给定的延迟。
31 ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit)
32 // 设置有关在此执行程序已 shutdown 的情况下是否继续执行现有定期任务的策略。
33 void setContinueExistingPeriodicTasksAfterShutdownPolicy(boolean value)
34 // 设置有关在此执行程序已 shutdown 的情况下是否继续执行现有延迟任务的策略。
35 void setExecuteExistingDelayedTasksAfterShutdownPolicy(boolean value)
36 // 在以前已提交任务的执行中发起一个有序的关闭,但是不接受新任务。
37 void shutdown()
38 // 尝试停止所有正在执行的任务、暂停等待任务的处理,并返回等待执行的任务列表。
39 List<Runnable> shutdownNow()
40 // 提交一个返回值的任务用于执行,返回一个表示任务的未决结果的 Future。
41 <T> Future<T> submit(Callable<T> task)
42 // 提交一个 Runnable 任务用于执行,并返回一个表示该任务的 Future。
43 Future<?> submit(Runnable task)
44 // 提交一个 Runnable 任务用于执行,并返回一个表示该任务的 Future。
45 <T> Future<T> submit(Runnable task, T result)
复制代码

 

7. Executors

Executors是个静态工厂类。它通过静态工厂方法返回ExecutorService、ScheduledExecutorService、ThreadFactory 和 Callable 等类的对象。

Executors函数列表

复制代码
 1 // 返回 Callable 对象,调用它时可运行给定特权的操作并返回其结果。2 static Callable<Object> callable(PrivilegedAction<?> action)3 // 返回 Callable 对象,调用它时可运行给定特权的异常操作并返回其结果。4 static Callable<Object> callable(PrivilegedExceptionAction<?> action)5 // 返回 Callable 对象,调用它时可运行给定的任务并返回 null。6 static Callable<Object> callable(Runnable task)7 // 返回 Callable 对象,调用它时可运行给定的任务并返回给定的结果。8 static <T> Callable<T> callable(Runnable task, T result)9 // 返回用于创建新线程的默认线程工厂。
10 static ThreadFactory defaultThreadFactory()
11 // 创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。
12 static ExecutorService newCachedThreadPool()
13 // 创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们,并在需要时使用提供的 ThreadFactory 创建新线程。
14 static ExecutorService newCachedThreadPool(ThreadFactory threadFactory)
15 // 创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。
16 static ExecutorService newFixedThreadPool(int nThreads)
17 // 创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程,在需要时使用提供的 ThreadFactory 创建新线程。
18 static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory)
19 // 创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。
20 static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
21 // 创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。
22 static ScheduledExecutorService newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory)
23 // 创建一个使用单个 worker 线程的 Executor,以无界队列方式来运行该线程。
24 static ExecutorService newSingleThreadExecutor()
25 // 创建一个使用单个 worker 线程的 Executor,以无界队列方式来运行该线程,并在需要时使用提供的 ThreadFactory 创建新线程。
26 static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory)
27 // 创建一个单线程执行程序,它可安排在给定延迟后运行命令或者定期地执行。
28 static ScheduledExecutorService newSingleThreadScheduledExecutor()
29 // 创建一个单线程执行程序,它可安排在给定延迟后运行命令或者定期地执行。
30 static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory)
31 // 返回 Callable 对象,调用它时可在当前的访问控制上下文中执行给定的 callable 对象。
32 static <T> Callable<T> privilegedCallable(Callable<T> callable)
33 // 返回 Callable 对象,调用它时可在当前的访问控制上下文中,使用当前上下文类加载器作为上下文类加载器来执行给定的 callable 对象。
34 static <T> Callable<T> privilegedCallableUsingCurrentClassLoader(Callable<T> callable)
35 // 返回用于创建新线程的线程工厂,这些新线程与当前线程具有相同的权限。
36 static ThreadFactory privilegedThreadFactory()
37 // 返回一个将所有已定义的 ExecutorService 方法委托给指定执行程序的对象,但是使用强制转换可能无法访问其他方法。
38 static ExecutorService unconfigurableExecutorService(ExecutorService executor)
39 // 返回一个将所有已定义的 ExecutorService 方法委托给指定执行程序的对象,但是使用强制转换可能无法访问其他方法。
40 static ScheduledExecutorService unconfigurableScheduledExecutorService(ScheduledExecutorService executor)
复制代码

 

线程池示例

下面通过示例来对线程池的使用做简单演示。

复制代码
 1 import java.util.concurrent.Executors;2 import java.util.concurrent.ExecutorService;3 4 public class ThreadPoolDemo1 {5 6     public static void main(String[] args) {7         // 创建一个可重用固定线程数的线程池8         ExecutorService pool = Executors.newFixedThreadPool(2);9         // 创建实现了Runnable接口对象,Thread对象当然也实现了Runnable接口
10         Thread ta = new MyThread();
11         Thread tb = new MyThread();
12         Thread tc = new MyThread();
13         Thread td = new MyThread();
14         Thread te = new MyThread();
15         // 将线程放入池中进行执行
16         pool.execute(ta);
17         pool.execute(tb);
18         pool.execute(tc);
19         pool.execute(td);
20         pool.execute(te);
21         // 关闭线程池
22         pool.shutdown();
23     }
24 }
25 
26 class MyThread extends Thread {
27 
28     @Override
29     public void run() {
30         System.out.println(Thread.currentThread().getName()+ " is running.");
31     }
32 }
复制代码

运行结果

pool-1-thread-1 is running.
pool-1-thread-2 is running.
pool-1-thread-1 is running.
pool-1-thread-2 is running.
pool-1-thread-1 is running.

结果说明
主线程中创建了线程池pool,线程池的容量是2。即,线程池中最多能同时运行2个线程。
紧接着,将ta,tb,tc,td,te这3个线程添加到线程池中运行。
最后,通过shutdown()关闭线程池。

 

转载于:https://www.cnblogs.com/kexianting/p/8549795.html

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

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

相关文章

c 试水解码jpeg图片比特流(已成功解码)

找到一张采用霍夫曼通用DC,AC编码表的图片&#xff0c;提取出此图片的比特流准备对它解码&#xff0c;再反推怎样编码。 下图是此图片比特流前100个字节。解码是每次读一字节&#xff0c;对这8比特解码&#xff0c;如8比特不能解码&#xff0c;再读入一字节。因为霍夫曼表最多…

Raft算法详解

Raft算法属于Multi-Paxos算法&#xff0c;它是在Multi-Paxos思想的基础上&#xff0c;做了一些简化和限制&#xff0c;比如增加了日志必须是连续的&#xff0c;只支持领导者、跟随者和候选人三种状态&#xff0c;在理解和算法实现上都相对容易许多 从本质上说&#xff0c;Raft算…

淘宝弹性布局方案lib-flexible研究

1. lib-flexible不能与响应式布局兼容 先说说响应式布局的一些基本认识&#xff1a; 响应式布局的表现是&#xff1a;网页通过css媒介查询判断可视区域的宽度&#xff0c;在不同的范围应用不同的样式&#xff0c;以便在不同尺寸的设备上呈现最佳的界面效果。典型的例子是&#…

WPF效果第一百九十四篇之伸缩面板

前面一篇玩耍了一下登录实现效果;今天在原来的基础上来玩耍一下伸缩面板的效果;闲话不多扯直接看效果:1、关于前台简单布局:2、左侧面板伸缩动画&#xff1a;<Storyboard x:Key"ShowConfigSb"><ThicknessAnimationUsingKeyFrames Storyboard.TargetProperty…

【.NET 6】开发minimal api以及依赖注入的实现和代码演示

前言&#xff1a;.net 6 LTS版本发布已经有一段时间了。此处做一个关于使用.net 6 开发精简版webapi&#xff08;minimal api&#xff09;的入门教程演示。1、新建一个项目。此处就命名为 SomeExample:2、选择 .net6版本&#xff0c;并且此处先去掉HTTPS配置以及去掉使用控制器…

(转载)VS2010/MFC编程入门之四(MFC应用程序框架分析)

上一讲鸡啄米讲的是VS2010应用程序工程中文件的组成结构&#xff0c;可能大家对工程的运行原理还是很模糊&#xff0c;理不出头绪&#xff0c;毕竟跟C编程入门系列中的例程差别太大。这一节鸡啄米就为大家分析下MFC应用程序框架的运行流程。 一.SDK应用程序与MFC应用程序运行过…

2022年中国中小学教育信息化行业研究报告

教育信息化丨研究报告 核心摘要&#xff1a; 背景篇 目前&#xff0c;我国中小学教育主要呈现信息时代教育的特征&#xff0c;智能时代教育特征初露端倪&#xff1b;中小学教育信息化正从量变迈向质变&#xff0c;创新引领与生态变革成为行业纵深的主旋律&#xff1b; 2021年…

使用curl指令发起websocket请求

昨日的文章没指出websocket请求协商切换的精髓&#xff0c;删除重发。前文相关&#xff1a;• .NET WebSockets 核心原理初体验[1]• SignalR 从开发到生产部署避坑指南[2]tag&#xff1a;浏览器--->nginx--> server其中提到nginx默认不会为客户端转发Upgrade、Connectio…

Yii 2 的安装 之 踩坑历程

由于刚接触yii2 ,决定先装个试试&#xff1b;可是这一路安装差点整吐血&#xff0c;可能还是水平有限吧&#xff0c; 但还是想把这个过程分享出来&#xff0c;让遇到同样问题的同学有个小小的参考&#xff0c;好了言归正传&#xff01;&#xff01; <(~.~)> 下面是安装流…

设计模式之代理模式(上) 静态代理与JDK动态代理

2019独角兽企业重金招聘Python工程师标准>>> 代理模式 给某一个对象提供一个代理&#xff0c;并由代理对象控制对原对象的引用。静态代理 静态代理是由我们编写好的类&#xff0c;在程序运行之前就已经编译好的的类&#xff0c;此时就叫静态代理。 说理论还是比较懵…

WPF 实现更换主题色

WPF 实现更换主题色WPF 使用 WPFDevelopers.Minimal 如何更换主题色作者&#xff1a;WPFDevelopersOrg原文链接&#xff1a; https://github.com/WPFDevelopersOrg/WPFDevelopers.Minimal框架使用大于等于.NET40&#xff1b;Visual Studio 2022;项目使用 MIT 开源许可协议&a…

vue3与vue2的区别

先来说说当下市场开发使用的问题&#xff0c;目前2021年使用vue3开发的企业还是少&#xff0c;基本上都还是以vue2的形式进行开发&#xff0c;vue3的开发模式跟react很像&#xff0c;这时候有人就会想那我学vue3有用么&#xff0c;淦&#xff0c;他喵的&#xff0c;先别激动&am…

Spring Data REST API集成Springfox、Swagger

原文: Documenting a Spring Data REST API with Springfox and Swagger 使用Spring Date REST&#xff0c;你可以迅速为Spring Date repositories的创建REST API&#xff0c;并提供CRUD和更多功能。然而&#xff0c;在严谨的API开发过成功&#xff0c;您还希望拥有自动生成的最…

【系统设计】S3 对象存储

在本文中&#xff0c;我们设计了一个类似于 Amazon Simple Storage Service (S3) 的对象存储服务。S3 是 Amazon Web Services (AWS) 提供的一项服务&#xff0c; 它通过基于 RESTful API 的接口提供对象存储。根据亚马逊的报告&#xff0c;到 2021 年&#xff0c;有超过 100 万…

转: telnet命令学习

1.每天一个linux命令&#xff08;58&#xff09;&#xff1a;telnet命令 转自&#xff1a; http://www.cnblogs.com/peida/archive/2013/03/13/2956992.html telnet命令通常用来远程登录。telnet程序是基于TELNET协议的远程登录客户端程序。Telnet协议是TCP/IP协议族中的一员&a…

禅道、码云、coding、redmine、jira、teambition几大敏捷开发项目管理系统试用对比体验

作为一个软件公司的管理人员&#xff0c;在项目和人员多起来后&#xff0c;就需要通过系统来对项目和人员进行管理。 我们是典型的软件外包公司&#xff0c;专为客户定制软件&#xff0c;所以我们的业务都是项目型的。因此&#xff0c;在管理模式上&#xff0c;我们就要用所谓…

Dubbo中的SPI机制

Dubbo中的SPI机制 概述 Service Provider Interface 即 SPI&#xff0c;是JDK内置的一种服务提供发现机制&#xff0c;可以用来启用框架扩展和替换组件。可以让不同的厂商针对统一接口编写不同的实现 SPI实际上是“接口策略模式配置文件”实现的动态加载机制。在系统设计中&…

JWT:拥有我,即拥有权力

Hi&#xff0c;这里是桑小榆。上篇文章中&#xff0c;我们一起探讨了 OAuth 协议的原理以及授权认证流程&#xff0c;本次我们一起探讨 jwt 令牌作为授权协议的传输介质。OAuth协议规范了几个参与角色的授权标准&#xff0c;安全可控的授予第三方应用&#xff0c;第三方应用获取…

双十一到来之前,阿里AI设计师“鲁班”1天能做4000万张海报

相比较去年&#xff0c;“鲁班”的设计技艺有所提升。 人工智能很大程度上便利了我们的生活&#xff0c;现在他们甚至还能取代了一些设计师的工作&#xff0c;在双十一正式到来之前&#xff0c;淘宝的宣传已经铺天盖地&#xff0c;然而很多人都没想到&#xff0c;我们打开淘宝…

Appium移动自动化测试之获取appPackage和appActivity

方法一&#xff1a;直接打开Appium,点击左上角机器人图标 选择apk所在位置&#xff0c;如图所示&#xff0c;这里以ContactManager.apk为例 方法二&#xff1a;利用dex2jar和jd-gui这两个工具反编译apk文件 这里仍以ContactManager.apk为例 (1)重命名ContactManager.apk为Conta…