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

Java Executor ScheduledExecutorService 源码

前言


 相关系列

  • 《Java & Executor & 目录》
  • 《Java & Executor & ScheduledExecutorService & 源码》
  • 《Java & Executor & ScheduledExecutorService & 总结》
  • 《Java & Executor & ScheduledExecutorService & 问题》
     

 涉及内容

  • 《Java & Executor & 总结》
  • 《Java & Executor & ExecutorService & 总结》
     
     

概述


 简介

在这里插入图片描述

    ScheduledExecutorService @ 调度执行器服务接口定义了“调度”概念。调度执行器服务接口是在ExecutorService @ 执行器服务接口的子接口,其在原本的基础上再度新增了“调度”概念。所谓调度可以理解为定时执行,即令任务在指定时间点被执行,而非在可执行时立即执行。

    调度执行器服务接口将“调度”概念细分为“延迟/周期”。“延迟”概念顾名思义,即任务会在其可执行的时间点上延迟指定时间后执行。这种延迟是人为规定的,与任务的执行机制无关。而大部分执行器由于自身任务执行机制的原因虽然也可能造成延迟,但这种延迟并非人为规定,因此与“延迟”概念没有关系。由此可知虽然调度执行器服务接口支持指定任务的延迟时间,但在任务具体执行时其实际延迟时间可能比指定延迟时间更长/短。此外调度执行器服务接口支持零/负延迟,当延迟时间被指定为零/负值时任务会被立即执行。关于“周期”的概念很也好理解,即令任务周期性地重复执行。通过对这两种概念进行组合,调度执行器服务接口可实现无延迟单次执行/有延迟单次执行/无延迟周期执行/有延迟周期执行四种任务调度形式。
 
 

源码


/** ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.*********************//******* Written by Doug Lea with assistance from members of JCP JSR-166* Expert Group and released to the public domain, as explained at* http://creativecommons.org/publicdomain/zero/1.0/*/package juc;import java.util.Date;/*** An {@link ExecutorService} that can schedule commands to run after a given delay, or to execute periodically.* 一个可以调度命令在指定延迟后运行,或周期性执行的执行器服务。* <p>* The {@code schedule} methods create tasks with various delays and return a task object that can be used to cancel or* check execution. The {@code scheduleAtFixedRate} and {@code scheduleWithFixedDelay} methods create and execute* tasks that run periodically until cancelled.* schedule()方法随着可变的延迟创建任务并返回一个可用于取消和检查执行的任务对象。scheduleAtFixedRate()和* scheduleWithFixedDelay()方法会周期性地创建及执行任务直至取消。* <p>* Commands submitted using the {@link Executor#execute(Runnable)} and {@link ExecutorService} {@code submit} methods* are scheduled with a requested delay of zero. Zero and negative delays (but not periods) are also allowed in* {@code schedule} methods, and are treated as requests for immediate execution.* 使用execute和submit方法递交的命令随着0延迟请求调度。0和负延迟(但不可以是周期)在调度方法中也允许,并且被作为* 立即执行请求对待。* <p>* All {@code schedule} methods accept <em>relative</em> delays and periods as arguments, not absolute times or dates.* It is a simple matter to transform an absolute time represented as a {@link Date} to the required form. For example, to* schedule at a certain future {@code date}, you can use:* {@code schedule(task, date.getTime() - System.currentTimeMillis(), TimeUnit.MILLISECONDS)}.* Beware however that expiration of a relative delay need not coincide with the current {@code Date} at which the task* is enabled due to network time synchronization protocols, clock drift, or other factors.* 所有调度方法都接受相关联的延迟和周期作为参数【即存在针对各种时间格式的重载方法】,不单纯是时间或日期。这是个* 转变单纯时间作为日期用于需要格式的简单问题。例如,为了在某个未来时间调度,你可以使用:* schedule(task, date.getTime() - System.currentTimeMillis(), TimeUnit.MILLISECONDS)* 此外注意:由于网络时间同步规约,时钟漂移,或者其它因素,相对延迟的到期日期不必与启用任务的当前日期一致【即实际* 执行时间可能与计划执行时间存在误差...妈的说的这么晦涩是想难到谁?】。* <p>* The {@link Executors} class provides convenient factory methods for the ScheduledExecutorService implementations* provided in this package.* Executors类提供便利的调度执行器服务实现(在当前包中实现)的工厂方法。* <h3>Usage Example</h3>* 使用模板* <p>* Here is a class with a method that sets up a ScheduledExecutorService to beep every ten seconds for an hour:* 这是一个随着方法建立一个调度线程池执行器来在一小时内每十秒鸣响的类:* <pre> {@code* import static TimeUnit.*;* class BeeperControl {*   // 通过工厂方法快速创建一个调度线程池执行器。*   private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);**   public void beepForAnHour() {*     final Runnable beeper = new Runnable() {*       public void run() {*         System.out.println("beep");*       }*     };**     final ScheduledFuture<?> beeperHandle = scheduler.scheduleAtFixedRate(beeper, 10, 10, SECONDS);*     scheduler.schedule(new Runnable() {*       public void run() {*         beeperHandle.cancel(true);*       }*     }, 60 * 60, SECONDS);*   }* }}</pre>** @author Doug Lea* @since 1.5*/
public interface ScheduledExecutorService extends ExecutorService {/*** Creates and executes a one-shot action that becomes enabled after the given delay.* 创建和执行一个单在指定延迟之后可用的单次活动。** @param command the task to execute 用于执行的任务* @param delay   the time from now to delay execution 用于延迟执行的基于当前的时间* @param unit    the time unit of the delay parameter 延迟参数的时间单位* @return a ScheduledFuture representing pending completion of the task and whose {@code get()} method will return* {@code null} upon completion* 一个调度未来代表任务的待定完成并且get()方法在完成后将返回null* @throws RejectedExecutionException if the task cannot be scheduled for execution*                                    拒绝执行异常:如果任务无法被调度执行* @throws NullPointerException       if command is null*                                    空指针异常:如果命令为null* @Description: ------------------------------------------------------------- 名称 -------------------------------------------------------------* 调度* @Description: ------------------------------------------------------------- 作用 -------------------------------------------------------------* 向当前调度执行器服务递交在指定延迟后执行的可运行/任务,并返回追踪/获取可运行/任务执行状态/结果的调度未来。* 由于在递交可运行/任务时没有传入用于承载可运行/任务执行结果的变量,因此调度未来实际无法获取可运行/任务的执* 行结果,故而该方法返回的调度未来的get()方法将永远返回null。* @Description: ------------------------------------------------------------- 逻辑 -------------------------------------------------------------* ----*/public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit);/*** Creates and executes a ScheduledFuture that becomes enabled after the given delay.* 创建和执行一个在指定延迟后可用的调度未来。** @param callable the function to execute 用于指定的功能* @param delay    the time from now to delay execution 用于延迟执行的基于当前时间的时间* @param unit     the time unit of the delay parameter 延迟参数的时间单位* @param <V>      the type of the callable's result 可调用结果的类型* @return a ScheduledFuture that can be used to extract result or cancel* 一个可用于提取结果或取消的调度未来* @throws RejectedExecutionException if the task cannot be scheduled for execution*                                    拒绝执行异常:如果任务无法被调度执行* @throws NullPointerException       if command is null*                                    空指针异常:如果命令为null* @Description: ------------------------------------------------------------- 名称 -------------------------------------------------------------* 调度* @Description: ------------------------------------------------------------- 作用 -------------------------------------------------------------* 向当前调度执行器服务递交在指定延迟后执行的可调用/任务,并返回追踪/获取可调用/任务执行状态/结果的调度未来。* @Description: ------------------------------------------------------------- 逻辑 -------------------------------------------------------------* ----*/public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit);/*** Creates and executes a periodic action that becomes enabled first after the given initial delay, and subsequently with* the given period; that is executions will commence after {@code initialDelay} then {@code initialDelay+period}, then* {@code initialDelay + 2 * period}, and so on. If any execution of the task encounters an exception, subsequent* executions are suppressed. Otherwise, the task will only terminate via cancellation or termination of the executor.  If* any execution of this task takes longer than its period, then subsequent executions may start late, but will not* concurrently execute.* 创建和执行一个在指定初始延迟之后,并随着指定周期可用的周期性活动;该执行将在初始延迟之后的initialDelay+period* 时间,initialDelay + 2 * period时间开始,等等。如果任意【一次】任务的执行遭遇异常,随后执行将被禁止。此外,任务* 将只能通过取消或执行器的终止而终止。如果任意当前任务的执行占有比它的周期更长的时间,那么随后执行可能开始的较* 晚,但不会并发地执行【一个任务一个时间只能被一条线程执行】。** @param command      the task to execute 用于执行的任务* @param initialDelay the time to delay first execution 用于延迟首次执行的时间* @param period       the period between successive executions 介于两次连续执行的周期* @param unit         the time unit of the initialDelay and period parameters 初始延迟和周期参数的时间单位* @return a ScheduledFuture representing pending completion of the task, and whose {@code get()} method will throw an* exception upon cancellation* 一个调度未来代表任务的等待执行,并且get()方法将在取消后抛出异常。* @throws RejectedExecutionException if the task cannot be scheduled for execution*                                    拒绝执行异常:如果任务无法被调度执行* @throws NullPointerException       if command is null*                                    空指针异常:如果命令为null* @throws IllegalArgumentException   if period less than or equal to zero*                                    非法参数异常:如果周期小于等于0* @Description: ------------------------------------------------------------- 名称 -------------------------------------------------------------* 按固定速率调度* @Description: ------------------------------------------------------------- 作用 -------------------------------------------------------------* 向当前调度执行器服务递交在指定初始延迟后按指定周期周期性执行的可运行/任务,并返回追踪/获取可运行/任务执行状* 态/结果的调度未来。由于在递交可运行/任务时没有传入用于承载可运行/任务执行结果的变量,因此调度未来实际无法获* 取可运行/任务的执行结果,故而该方法返回的调度未来的get()方法将永远返回null。但又因为该方法递交的可运行/任务将* 在自身没有被取消/执行中没有抛出异常/当前调度执行器服务没有被终止的情况下永远周期性地执行下去,因此调度未来* 的get()方法要么因为上述情况抛出异常,要么因为无法获取到结果而无限等待。此外,即使可运行/任务的执行时间超过周* 期,下次执行依然会在距离上次执行开始时间点的指定周期后开始,并且上次执行会被取消(虽然可能无法响应)。* @Description: ------------------------------------------------------------- 逻辑 -------------------------------------------------------------* ----*/public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit);/*** Creates and executes a periodic action that becomes enabled first after the given initial delay, and subsequently with* the given delay between the termination of one execution and the commencement of the next.  If any execution of the* task encounters an exception, subsequent executions are suppressed. Otherwise, the task will only terminate via* cancellation or termination of the executor.* 创建并执行一个在指定初始延迟之后可用,并随着指定介于首次执行结束和下次执行开始的延迟执行的周期型活动。如果* 任意【一次】任务的执行遭遇一场,随后执行将被禁止。此外,任务将只能通过取消或执行器的终止而终止。** @param command      the task to execute 用于执行的任务* @param initialDelay the time to delay first execution 用于延迟首次执行的时间* @param delay        the delay between the termination of one execution and the commencement of the next*                     介于首次执行终止何下次执行开始的延迟* @param unit         the time unit of the initialDelay and period parameters 初始延迟和周期参数的时间单位* @return a ScheduledFuture representing pending completion of the task, and whose {@code get()} method will throw an* exception upon cancellation* 一个调度未来代表任务的等待执行,并且get()方法将在取消后抛出异常。* @throws RejectedExecutionException if the task cannot be scheduled for execution*                                    拒绝执行异常:如果任务无法被调度执行* @throws NullPointerException       if command is null*                                    空指针异常:如果命令为null* @throws IllegalArgumentException   if period less than or equal to zero*                                    非法参数异常:如果周期小于等于0* @Description: ------------------------------------------------------------- 名称 -------------------------------------------------------------* 随固定延迟调度* @Description: ------------------------------------------------------------- 作用 -------------------------------------------------------------* 向当前调度执行器服务递交在指定初始延迟后按指定延迟周期性执行的可运行/任务,并返回追踪/获取可运行/任务执行状* 态/结果的调度未来。由于在递交可运行/任务时没有传入用于承载可运行/任务执行结果的变量,因此调度未来实际无法获* 取可运行/任务的执行结果,故而该方法返回的调度未来的get()方法将永远返回null。但又因为该方法递交的可运行/任务将* 在自身没有被取消/执行中没有抛出异常/当前调度执行器服务没有被终止的情况下永远周期性地执行下去,因此调度未来* 的get()方法要么因为上述情况抛出异常,要么因为无法获取到结果而无限等待。此外,如果可运行/任务的执行时间超过周* 期,则下次执行会在距离上次执行结束时间点的指定延迟后开始。* @Description: ------------------------------------------------------------- 逻辑 -------------------------------------------------------------* ----*/public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit);}

相关文章:

Java Executor ScheduledExecutorService 源码

前言 相关系列 《Java & Executor & 目录》《Java & Executor & ScheduledExecutorService & 源码》《Java & Executor & ScheduledExecutorService & 总结》《Java & Executor & ScheduledExecutorService & 问题》 涉及内容 …...

【力扣 + 牛客 | SQL题 | 每日6题】牛客SQL热题 + 力扣hard

1. 牛客SQL热题206&#xff1a;获取每个部门中当前员工薪水最高的相关信息 1.1 题目&#xff1a; 描述 有一个员工表dept_emp简况如下: emp_nodept_nofrom_dateto_date10001d0011986-06-269999-01-0110002d0011996-08-039999-01-0110003d0021996-08-039999-01-01 有一个薪水…...

前端常见错误

搭建vueelement-ui脚手架错误 基于vue官方文档和element官方文档搭建手册报错 安装element Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist. types.js?8ad0:39 Uncaught TypeError: Cannot read property prototype of undefi…...

Edge 浏览器插件开发:图片切割插件

Edge 浏览器插件开发&#xff1a;图片切割插件 在图片处理领域&#xff0c;按比例切割图片是一个常见需求。本文将带你开发一个 Edge 浏览器插件&#xff0c;用于将用户上传的图片分割成 4 个部分并自动下载到本地。同时&#xff0c;本文介绍如何使用 cursor 辅助工具来更高效…...

银河麒麟v10 xrdp安装

为了解决科技被卡脖子的问题&#xff0c;国家正在大力推进软硬件系统的信创替代&#xff0c;对于一些平时对Linux操作系统不太熟练的用户来讲提出了更高的挑战和要求。本文以银河麒麟v10 24.03为例带领大家配置kylin v10的远程桌面。 最近公司为了配置信创开发新购了几台银河麒…...

Leetcode 删除有序数组中的重复项 Ⅱ

使用双指针来解决此问题&#xff0c;关键词“有序”数组&#xff0c;一个 index 指针用于构建新数组&#xff0c;一个 i 指针用于遍历整个数组 以下是代码的中文解释以及算法思想&#xff1a; 算法思想 这道题要求对一个有序数组进行去重&#xff0c;使得每个元素最多出现两…...

大模型学习笔记------什么是大模型

大模型学习笔记------什么是大模型 1、大模型定义2、大模型发展历程3、大模型的核心特点4、大模型的应用领域5、大模型面临的挑战6、结束语 近两年大模型超级火&#xff0c;并且相关产品迎来爆发式增长。在工作中&#xff0c;也常常接触到大模型&#xff0c;并且已经开始进行相…...

【unique_str 源码学习】

文章目录 &#xff11;&#xff0e;删除器定义2. operator->() 运算符重载3. add_lvalue_reference<element_type>::type 使用 基本原理这篇博主写的很详细 https://yngzmiao.blog.csdn.net/article/details/105725663 &#xff11;&#xff0e;删除器定义 deleter_…...

flask第一个应用

文章目录 安装一、编程第一步二、引入配置三、代码解析 安装 python环境安装的过程就不重复赘述了&#xff0c;flask安装使用命令pip install Flask即可&#xff0c;使用命令pip show Flask查看flask版本信息 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供…...

华为OD机试真题(Python/JS/C/C++)- 考点 - 细节

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题 点这里。 本专栏收录于《华为OD机试真题&#xff08;Python/JS/C/C&#xff09;》。...

【C++刷题】力扣-#628-三个数的最大乘积

题目描述 给你一个整型数组 nums &#xff0c;在数组中找出由三个数组成的最大乘积&#xff0c;并输出这个乘积。 示例 示例 1 输入&#xff1a;nums [1,2,3] 输出&#xff1a;6示例 2 输入&#xff1a;nums [1,2,3,4] 输出&#xff1a;24示例 3 输入&#xff1a;nums […...

Java项目实战II基于Java+Spring Boot+MySQL的工程教育认证的计算机课程管理平台(源码+数据库+文档)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 随着工程教…...

基于微信小程序实现信阳毛尖茶叶商城系统设计与实现

作者简介&#xff1a;Java领域优质创作者、CSDN博客专家 、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验&#xff0c;被多个学校常年聘为校外企业导师&#xff0c;指导学生毕业设计并参与学生毕业答辩指导&#xff0c;…...

设计一个灵活的RPC架构

RPC架构 RPC本质上就是一个远程调用&#xff0c;需要通过网络来传输数据。传输协议可以有多种选择&#xff0c;但考虑到可靠性&#xff0c;一般默认采用TCP协议。为了屏蔽网络传输的复杂性&#xff0c;需要封装一个单独的数据传输模块用来收发二进制数据&#xff0c;这个单独模…...

大数据计算里的Broadcast Hash Join/Shuffle Hash Join/Sort Merge Join

文章目录 Broadcast Hash Join场景 Shuffle Hash Join场景 Sort Merge Join场景 Broadcast Hash Join 场景 大表和小小表&#xff0c;直接把B表加载到内存&#xff0c;然后读块1内容和内存中数据匹配 Shuffle Hash Join 场景 大表和小表JOIN &#xff0c;小表分块后能加载…...

Java - 手写识别; 如何用spring ai和大模型做手写识别教程

识别后的文字 利用大模型提升Java手写识别&#xff1a;更简单、更高效 在Java场景中&#xff0c;我们经常需要处理手写识别的问题。过去&#xff0c;这类需求主要依赖于OCR技术&#xff0c;但其效果并不总是稳定。随着大模型的发展&#xff0c;使用大模型进行java手写识别成为…...

【Linux】用户权限管理:创建受限用户并配置特定目录访问权限

本文详细介绍了如何在 Linux 系统中创建一个名为 agent 的新用户&#xff0c;并限制其在特定目录下的权限。通过使用 useradd 命令创建用户&#xff0c;并使用 usermod 命令将新用户添加到现有用户组中&#xff0c;确保其具有适当的权限。接着&#xff0c;通过 chown 和 chmod …...

pgsql表分区和表分片设计

在设计 PostgreSQL 表分区和表分片时&#xff0c;主要目标是提高查询性能、可扩展性和数据管理的效率。以下是一些关键的设计步骤和策略&#xff1a; 1. 分区策略 水平分片&#xff1a;选择按日期进行水平分片&#xff0c;每天一个分片。这种策略适用于具有时间序列数据的场景…...

灵动AI ——视频创作新引擎 开启视觉奇幻之旅

灵动AI视频官网地址&#xff1a;https://aigc.genceai.com/ 灵动AI 科技与艺术的完美融合之作。它代表着当下最前沿的影像技术&#xff0c;为我们带来前所未有的视觉盛宴。...

AI设计、作图、画画工具哪个好用?看完这篇你就知道怎么选了

Stable Diffusion Stable Diffusion 是由 Stability AI 推出的开源 AI 文本到图像生成模型&#xff0c;以其开放性和灵活性在 AI 视觉工具领域广受欢迎。与 DALL-E 或 Midjourney 等只能依赖云计算的工具不同&#xff0c;Stable Diffusion 支持本地运行&#xff0c;也广泛兼容多…...

【python ASR】win11-从0到1使用funasr实现本地离线音频转文本

文章目录 前言一、前提条件安装环境Python 安装安装依赖,使用工业预训练模型最后安装 - torch1. 安装前查看显卡支持的最高CUDA的版本&#xff0c;以便下载torch 对应的版本的安装包。torch 中的CUDA版本要低于显卡最高的CUDA版本。2. 前往网站下载[Pytorch](https://pytorch.o…...

myqld二进制安装和破解数据库密码(linux)

安装和基本配置 1.首先把下载下来的mysql安装包放到本地这里下载的是5.7版本为演示 1&#xff09;解压 tar xf mysql-5.7.20-linux-glibc2.12-x86_64.tar.gz -C /usr/local -把安装包解压到/usr/local cd /usr/local …...

防重方案-订单防重方案笔记

订单防重设计 订单重复提交概念解决方案前端防重机制后端防重机制利用Token机制基于数据库的唯一索引 Token机制方案介绍 其他 订单重复提交概念 重复提交指&#xff0c;连点按钮进行重复提交操作&#xff0c;不包括刷新后的重新下单&#xff0c;重新下单已非同一订单的概念。…...

HTML、JavaScript和CSS实现注册页面设计

目录 一、实现要求 二、实现页面图 1、注册页面 2.用户ID、用户名、口令验证成功后显示页面 三、用户ID、用户名、口令、确定口令验证逻辑js代码 1、验证用户ID 2、验证用户名 3、验证口令密码 四、总结 五、代码仓库 一、实现要求 综合使用HTML、JavaScript和CSS进…...

Counter对象的使用样例

1. Counter类的定义和功能说明 Counter是一个用于跟踪值出现次数的有序集合。它可以接收一个可迭代对象作为参数&#xff0c;并生成一个字典&#xff0c;其中包含每个元素作为键&#xff0c;其计数作为值。 2. 统计列表或字符串中元素的出现次数 示例代码&#xff1a; from…...

大模型中的token是什么;常见大语言模型的 token 情况

目录 大模型中的token是什么 常见大语言模型的 token 情况 大模型中的token是什么 定义 在大模型中,token 是文本处理的基本单位。它可以是一个字、一个词,或者是其他被模型定义的语言单元。简单来说,模型在理解和生成文本时,不是以完整的句子或段落为单位进行一次性处理…...

Python小白学习教程从入门到入坑------第十七课 内置函数拆包(语法基础)

一、内置函数 1.1 查看所有内置函数 内置函数&#xff1a;Python 提供了许多内置函数&#xff0c;这些函数无需导入任何模块即可直接使用。它们涵盖了各种用途&#xff0c;从数学运算到类型检查&#xff0c;再到输入输出操作等。 如何查看内置函数呢&#xff1f; 在Pycharm…...

动态规划 —— 路径问题-最小路径和

1. 最小路径和 题目链接&#xff1a; 64. 最小路径和 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/minimum-path-sum/description/ 2. 算法原理 状态表示&#xff1a;以莫一个位置位置为结尾 dp[i&#xff0c;j]表示&#xff1a;到达[i&#xff0c;j…...

《链表篇》---删除链表的倒数第N个节点(中等)

题目传送门 方法一&#xff1a;计算链表长度&#xff08;迭代&#xff09; 1.计算链表长度&#xff0c;并且定义哑节点链接链表。 2.从哑节点开始前进length-n次。即为被删除节点的前置节点。 3.进行删除操作。 4.返回哑节点的后置节点 class Solution {public ListNode remo…...

duilib 进阶 之 TileListBox 列表

目录 一、TileListBox 1、样式 1)、整体列表分列设置 2)、列表项样式设置 3)、选中后出现√号,horver时 出现边框色 的实例 2、代码 1)、普通动态添加列表项 2)、列表项样式中有自定义控件时 3)、获得选中项 一、TileListBox Tile [taɪl] ,瓦片 棋子 Ti…...