最近天气很冷,记得保暖,我在帝都向各位问好。一次舒服的小长假回来,是不是都忘了增删改查怎么敲了,那就赶紧粘贴一会儿吧,别等着公司把你优化掉。

好了,老习惯,首先给各位脑补一下多线程必备的知识。

进程和线程:

下图是在来自知乎用户的解释,个人感觉狠到位

多线程编程:多线程并发制单的开发记录【一】

       进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。

       线程,有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。线程是程序中一个单一的顺序控制流程。进程内一个相对独立的、可调度的执行单元,是系统独立调度和分派CPU的基本单位指运行中的程序的调度单位。在单个程序中同时运行多个线程完成不同的工作,称为多线程。

进程和线程的关系:

多线程编程:多线程并发制单的开发记录【一】

 

线程安全:

       何为线程安全?就是应用中多个线程访问某一个类(对象或方法)时,这个类始终能表现出正确的行为,那么这个类(对象或方法)就是线程安全的。

       线程安全就是多线程访问时,采用了加锁机制(在多线程安全上加锁也是一门技术活,不是说对于共享资源你简单加个同步关键字或定义成同步方法就OK了的,锁的不合理则会大大影响程序的性能,甚至影响到业务,这里本人亲身经历过一个问题,锁粒度大小对程序的影响,参考:http://www.cnblogs.com/1315925303zxz/p/7561236.html),当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。

        线程不安全呢,就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据。这里的加锁机制常见的如:synchronized。

由spring管理的线程池进行并发制单的业务设计:

业务需求:多个通道进行数据采集,数据采集就是拿着VIN码去抓取数据,但是当VIN码很多时,采集的速度就很慢,所以实施多线程多并发进行采集。

1、spring管理线程池的配置,这里需要说明的一点就是核心线程数和最大线程数的配置一定要按照自己业务的并发量来设定,否则不仅不会提升并发效率,反而会出现各种数据污染的情况。

 1    <!-- 异步线程池 -->
 2     <bean id="threadPoolTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
 3         <!-- 核心线程数,最小线程数 默认为1 -->
 4         <property name="corePoolSize" value="4" />
 5         <!-- 最大线程数,默认为Integer.MAX_VALUE -->
 6         <property name="maxPoolSize" value="8" />
 7         <!-- 队列最大长度,一般需要设置值>=notifyScheduledMainExecutor.maxNum;默认为Integer.MAX_VALUE -->
 8         <property name="queueCapacity" value="2000" /> 
 9         <!-- 线程池维护线程所允许的空闲时间,默认为60s -->
10         <property name="keepAliveSeconds" value="300" />
11         <!-- 线程池对拒绝任务(无线程可用)的处理策略,目前只支持AbortPolicy、CallerRunsPolicy;默认为后者 -->
12         <property name="rejectedExecutionHandler">
13             <!-- AbortPolicy:直接抛出java.util.concurrent.RejectedExecutionException异常 -->
14             <!-- CallerRunsPolicy:主线程直接执行该任务,执行完之后尝试添加下一个任务到线程池中,可以有效降低向线程池内添加任务的速度 -->
15             <!-- DiscardOldestPolicy:抛弃旧的任务、暂不支持;会导致被丢弃的任务无法再次被执行 -->
16             <!-- DiscardPolicy:抛弃当前任务、暂不支持;会导致被丢弃的任务无法再次被执行 -->
17             <bean class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy" />
18         </property>
19     </bean>

     <!-- 一汽大众和奥迪多并发制单 -->
      <bean />

 

2、线程制单业务(这里是伪代码),将符合条件的VIN码进行数据采集,否则记录到指定容器中统一处理(退单)。

初始化任务(VIN码)队列:

 1 public 
 2 class InitQueue {
 3     
 4     private static final Logger logger = LoggerFactory.getLogger(MultiThreadTask_VW_AD.class);
 5     
 6     /**
 7      *    并发队列
 8      */
 9     private static Queue<String> queue = null;
10     
11     //初始化并发队列
12     private static void initQueue(){
13         logger.info("初始化并发队列:{}");
14         if(queue == null){
15             queue = new ConcurrentLinkedQueue<String>();    //并发队列    
16         }
17         String tasklist = "JF1GH78F18G03614,JF1SH95F6AG110830,JF1SJ94D7DG010387333,JF1SH92F9CG26924,JF1SH92F5BG215090,JF1SH92F5BG222556,JF1SH92F4CG279994,JF1BR96D7CG114298,JF1BR96D0BG078632,JF1SH95F9AG094011,JF1SH98FXAG186997,JF1BM92D8BG022510,JF1BM92DXAG013855,JF1BM94D8EG0366";
18         String[] split = tasklist.split(",");
19         List<String> task = Arrays.asList(split);    //数组转集合
20         queue.addAll(task);        //按照集合中元素的顺序将集合中全部元素放进队列
21     }
22     
23     //对外提供一个任务队列
24     public static Queue<String> getQueue(){
25         initQueue();
26         return queue;
27     }
28 
29 }
View Code

相关文章:

  • 2022-01-13
  • 2021-12-04
  • 2021-11-18
  • 2021-07-21
  • 2021-07-16
  • 2022-12-23
  • 2022-12-23
  • 2021-11-21
猜你喜欢
  • 2021-07-08
  • 2021-10-21
  • 2022-01-02
相关资源
相似解决方案