java多线程处理持续任务

package com.winterchen.service.thread;

import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.winterchen.dao.ThreadTaskDao;

@Service
public class ThreadTaskDemo {

    @Autowired
    ThreadTaskDao threadTaskDao;
    
    //最大线程数
    public static int maxThreadCount = 100;
    
    //线程池
    public ExecutorService executorService = Executors.newFixedThreadPool(ThreadTaskDemo.maxThreadCount);
    
    //处理的任务列表
    public static List<Map<String,Object>> curTaskList = new CopyOnWriteArrayList<Map<String,Object>>();
    
    
    /**
     * 任务处理
     */
    public void taskExec(){
        int execTotalCount = 0;
        try{
            while(true){
                
                //删除已处理完的对象
                for(Map<String,Object> curTaskMap : curTaskList){
                    if(curTaskMap.get("taskFlag").equals("1")){
                        curTaskList.remove(curTaskMap);
                        /* Iterator<Map<String,Object>> it_b= ThreadTaskDemo.curTaskList.iterator();
                          while(it_b.hasNext()){
                            Map<String,Object> a=it_b.next();
                            if (a.get("id").equals(map.get("id"))) {
                                it_b.remove();
                            }
                        }*/
                    }
                }
                
                System.out.println(execTotalCount++  + "——————————————————————————————开始任务,当前任务数: " + curTaskList.size() +"————————————————————————");
                
                List<Map<String,Object>> taskList = threadTaskDao.selectTasks();
                
                if(taskList.size() > 0){
                    
                    int addNewCount = 0;
                    
                    //添加新任务(需要去除正在执行的任务,避免重复处理)
                    for(Map<String,Object> newMap : taskList){
                        boolean isExists = false;    
                        
                        for(Map<String,Object> curTaskMap : curTaskList){
                            if(newMap.get("id").equals(curTaskMap.get("id"))){
                                isExists = true;
                                break;
                            }
                        }
                        
                        //新任务,处理
                        if(!isExists){
                            if(curTaskList.size() < ThreadTaskDemo.maxThreadCount){
                                addNewCount ++;
                                curTaskList.add(newMap);
                                executorService.execute(new RunnableThreadDemo1(newMap,threadTaskDao));
                            }
                        }
                    }
                    
                    System.out.println("——————————————————————————————新加"+ addNewCount +" 个任务,当前任务数:"+ curTaskList.size());
                    
                }
                //等待1秒执行
                Thread.sleep(1000);
            }
        }catch(Exception e){
            e.printStackTrace();
        }
        
    }
    
}


class RunnableThreadDemo1 implements Runnable{

    private Map<String,Object> map;
    private ThreadTaskDao threadTaskDao;
    
    public RunnableThreadDemo1(Map<String,Object> map,ThreadTaskDao threadTaskDao){
        this.map = map;
        this.threadTaskDao = threadTaskDao;
    }
    
    @Override
    public void run() {
        try {
            Long execTime = Long.valueOf((Integer) map.get("execTime")*100);
            System.out.println();
            System.out.println(map.get("taskCode") + " 等待时长:" + execTime/1000 + " 秒");
            Thread.sleep(execTime);
            threadTaskDao.udpateTaskById(String.valueOf(map.get("id")));
            //标识已完成
            map.put("taskFlag", "1");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    
}
 

<select id="selectTasks" resultType="map">
      SELECT id,task_code AS taskCode,task_name AS taskName,
        exec_time AS execTime,remark,task_flag AS taskFlag 
        FROM `t_thread_task`
        WHERE task_flag = '0'
        LIMIT 0,100
    </select>
    
     <update id="udpateTaskById" parameterType="string">
        <![CDATA[
            update `t_thread_task` set task_flag = '1',
            exec_num = exec_num +1
            where id =  #{id}
        ]]>
     </update>

Create Table

CREATE TABLE `t_thread_task` (
  `id` int NOT NULL AUTO_INCREMENT,
  `task_code` varchar(255) NOT NULL,
  `task_name` varchar(255) NOT NULL,
  `exec_time` int DEFAULT '0',
  `remark` varchar(200) DEFAULT NULL,
  `task_flag` varchar(1) NOT NULL DEFAULT '0',
  `exec_num` int NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 可以使用Kafka提供的Java客户端API来实现多线程消费Kafka消息。具体步骤如下: 1. 创建Kafka消费者实例,设置消费者配置参数,如bootstrap.servers、group.id等。 2. 创建多个消费线程,每个线程都创建一个Kafka消费者实例并订阅相同的Kafka主题。 3. 在每个消费线程中,使用Kafka消费者实例的poll()方法从Kafka主题中拉取消息。 4. 处理拉取到的消息,可以将消息放入线程安全的队列中,由其他线程进行处理。 5. 在消费线程中,使用Kafka消费者实例的commitSync()方法提交消费偏移量,确保消息被成功处理。 6. 在主线程中,等待所有消费线程完成消费任务后,关闭Kafka消费者实例。 示例代码如下: ```java public class KafkaConsumerDemo { private static final String TOPIC_NAME = "test-topic"; private static final int NUM_THREADS = 3; public static void main(String[] args) { Properties props = new Properties(); props.put("bootstrap.servers", "localhost:9092"); props.put("group.id", "test-group"); props.put("enable.auto.commit", "false"); props.put("auto.offset.reset", "earliest"); props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer"); props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer"); ExecutorService executorService = Executors.newFixedThreadPool(NUM_THREADS); for (int i = 0; i < NUM_THREADS; i++) { executorService.execute(() -> { KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props); consumer.subscribe(Collections.singleton(TOPIC_NAME)); while (true) { ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100)); for (ConsumerRecord<String, String> record : records) { // 处理消息 System.out.printf("Thread: %s, offset: %d, key: %s, value: %s\n", Thread.currentThread().getName(), record.offset(), record.key(), record.value()); } consumer.commitSync(); } }); } Runtime.getRuntime().addShutdownHook(new Thread(() -> { executorService.shutdownNow(); })); } } ``` 上面的示例代码创建了3个消费线程,每个线程都创建了一个Kafka消费者实例,并订阅了名为test-topic的Kafka主题。在每个消费线程中,使用poll()方法从Kafka主题中拉取消息,并处理消息。在消费线程中,使用commitSync()方法提交消费偏移量。在主线程中,通过addShutdownHook()方法注册了一个钩子函数,用于在程序退出时关闭线程池。 ### 回答2: Java多线程消费Kafka是一种常见的消息消费方式,适用于需要高性能和高并发处理消息的场景。下面是一个简单的示例代码,用于演示Java多线程消费Kafka的基本思路。 1. 首先,我们需要引入Kafka的Java客户端依赖包,例如Apache Kafka提供的`kafka-clients`库。 2. 然后,我们创建一个消费者线程类`ConsumerThread`,实现`Runnable`接口,该类的主要功能是从Kafka主题订阅消息并进行处理。 3. 在`ConsumerThread`类的构造函数中,我们可以传入一些配置参数,例如Kafka的服务器地址、消费者组ID以及要消费的主题等。 4. 在`run()`方法中,我们可以实例化一个Kafka消费者对象,并设置消费者的配置参数。然后,通过`consumer.subscribe()`方法订阅指定的主题。 5. 在一个无限循环中,通过`consumer.poll()`方法从Kafka中拉取消息。拉取到的消息会被封装成一个`ConsumerRecords`对象。 6. 迭代`ConsumerRecords`对象,并逐条处理每条消息。处理的逻辑可以根据业务需求自定义,例如将消息保存到数据库、进行计算或者发送到其他系统等。 7. 最后,记得在合适的时候关闭消费者对象,释放资源。 使用多线程消费Kafka能够提高消息消费的效率和并发性。可以考虑将消费者线程实例化为一个线程池,并指定线程数,以实现并发处理。 需要注意的是,在多线程消费Kafka的场景下,可能会出现消息顺序不一致的情况。因此,需要根据业务需求来判断是否需要保持消息的顺序性。 ### 回答3: Java中可以使用Apache Kafka客户端库来实现多线程消费Kafka。多线程消费可以提高消费速度和并发性。 首先,我们需要创建一个Kafka消费者对象,指定要消费的主题和Kafka集群的地址。然后,我们可以使用该消费者对象来订阅要消费的主题。 接下来,我们可以创建多个线程来同时消费Kafka消息。每个线程都可以创建一个新的消费者实例,并在每个线程中运行一个消费循环,以接收并处理从Kafka中获取的消息。 在消费循环中,我们可以使用一个无限循环来持续地消费Kafka消息。在每次循环中,我们可以使用消费者对象的poll方法来获取一批新的消息。然后,我们可以遍历这批消息并进行相应的处理。 在处理消息的过程中,我们需要确保每个线程都能处理自己所接收到的消息,并且要考虑到线程安全性。可以使用锁或其他线程同步机制来保证多个线程之间的数据访问的一致性和互斥性。 此外,在处理消息的过程中,我们还可以对消息进行一些后续的处理,比如将消息保存到数据库、发送到其他系统或进行其他的业务逻辑操作。 最后,当需要停止消费线程时,我们可以调用消费者对象的close方法来关闭消费者。这将会释放消费者所占用的资源,并停止消费。 综上所述,通过创建多线程来消费Kafka消息可以提高消费速度和并发性,从而更好地满足高并发场景下的需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值