用Runable多线程跑任务提升速度

通过将单线程轮询转换为使用Runnable与ExecutorService执行多线程任务,显著提高了处理速度,将30000条数据的处理时间从3200秒减少到91秒,效率提升97%。

   之前在跑定时任务时,就单线程用for轮询,不仅慢,如果一个NPE还造成整个Task中断,用Runable就方便多了。

 

  1、定义一个task类,作为调用一个线程

  

  2、ExecutorService开启多个线程

ExecutorService executorService = Executors.newFixedThreadPool(dates.size())的dates.size就是线程数

  用30000条数据测试,由原来的3200秒减少到91秒,提升了97%

<think>好的,用户之前已经询问了关于Java中使用Runnable接口和Thread的区别,现在他们进一步要求举例说明Runnable的好处。需要回顾之前的回答,确保内容一致,同时用例子具体说明。用户可能是刚开始学习多线程,需要清晰、易懂的例子来理解理论。 首先,我应该先列举Runnable的主要优势,然后为每个优势提供一个具体的例子。比如,避免单继承限制的例子可以用一个类继承其他父类同时实现Runnable。资源共享的例子可以用多个线程操作同一个Runnable实例。线程池和任务分离的例子也很重要。另外,用户可能对实际应用场景感兴趣,比如售票系统,所以用售票的例子来说明资源共享会更直观。 需要注意例子要简单,代码段不宜过长,同时要注释解释。还要确保例子能准确反映每个好处,比如在单继承的例子中,展示类已经继承了另一个类,但仍然可以实现Runnable。在资源共享的例子中,展示多个线程共享同一个Runnable实例,操作同一数据,比如票数。线程池的例子则展示如何提交Runnable任务给Executor执行,说明其兼容性。 另外,用户可能对Lambda表达式简化代码的例子感兴趣,所以可以加入一个使用Lambda的简洁例子,展示如何替代匿名内部类,提高代码可读性。 需要检查每个例子的正确性,比如售票系统的synchronized关键字是否正确使用,确保线程安全。同时,确保代码格式正确,符合Java语法,比如类定义、方法重写等。 最后,总结各个好处,并强调Runnable在实践中的优势,帮助用户形成整体理解。可能还需要提醒用户在实际开发中的最佳实践,比如优先使用Runnable,结合线程池等。</think>以下是关于使用`Runnable`接口优势的具体示例解析: --- ### 一、**避免单继承限制** #### 示例场景 假设有一个类需要继承业务父类,同时还要实现多线程: ```java class DatabaseConnector extends ConnectionManager implements Runnable { // 可继承其他父类 @Override public void run() { // 执行数据库操作任务 System.out.println("正在执行数据库查询..."); } } // 使用方式 new Thread(new DatabaseConnector()).start(); ``` - **优势体现**:若使用继承`Thread`的方式,`DatabaseConnector`将无法再继承`ConnectionManager` --- ### 二、**资源共享能力** #### 示例场景(售票系统) ```java class TicketSeller implements Runnable { private int tickets = 10; // 总票数 @Override public void run() { while (tickets > 0) { synchronized (this) { // 线程安全控制 if (tickets > 0) { System.out.println(Thread.currentThread().getName() + " 售出第 " + tickets-- + " 张票"); } } } } } // 启动三个售票窗口共享票源 Runnable task = new TicketSeller(); new Thread(task, "窗口1").start(); new Thread(task, "窗口2").start(); new Thread(task, "窗口3").start(); ``` - **输出示例**: ``` 窗口1 售出第 10 张票 窗口3 售出第 9 张票 窗口2 售出第 8 张票 ...(剩余票数共享递减) ``` - **优势体现**:多个线程操作同一`Runnable`对象,天然支持资源共享 --- ### 三、**线程池兼容性** #### 示例场景 ```java ExecutorService pool = Executors.newFixedThreadPool(3); Runnable task1 = () -> System.out.println("处理用户请求"); Runnable task2 = () -> System.out.println("生成日志文件"); Runnable task3 = () -> System.out.println("发送通知邮件"); pool.execute(task1); pool.execute(task2); pool.execute(task3); pool.shutdown(); ``` - **优势体现**:线程池等高级并发工具直接支持`Runnable`,无需额外适配 --- ### 四、**任务与执行分离** #### 示例场景 ```java // 定义可复用的任务 class FileProcessor implements Runnable { private String fileName; public FileProcessor(String name) { this.fileName = name; } @Override public void run() { System.out.println("正在处理文件: " + fileName); } } // 灵活调度方式1:直接启动线程 new Thread(new FileProcessor("data.csv")).start(); // 灵活调度方式2:提交到定时任务 ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); scheduler.scheduleAtFixedRate( new FileProcessor("backup.zip"), 0, 1, TimeUnit.HOURS ); ``` - **优势体现**:同一任务可适配不同执行策略(立即执行、定时执行、延迟执行等) --- ### 五、**Lambda简化代码** #### 示例场景(Java8+) ```java // 传统匿名内部类写法 new Thread(new Runnable() { @Override public void run() { System.out.println("旧写法"); } }).start(); // Lambda表达式简化写法 new Thread(() -> System.out.println("新写法")).start(); ``` - **优势体现**:代码行数减少60%,可读性显著提升 --- ### 总结对比表 | 场景 | 使用`Runnable`的代码量 | 使用`Thread`的代码量 | 可维护性 | |--------------------|-----------------------|----------------------|----------| | 资源共享 | 1个对象+N次`new Thread()` | 需要创建N个独立子类 | ✅ 更优 | | 继承其他类 | 允许 | 无法实现 | ✅ 必须 | | 线程池支持 | 直接使用`execute()` | 需要额外封装 | ✅ 更优 | | 代码复用 | 任务对象可重复使用 | 每次需新建线程对象 | ✅ 更优 | 通过以上具体示例,可以清晰看到`Runnable`接口在代码灵活性、资源利用率和架构设计上的显著优势。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值