java处理线程阻塞的小技巧
2017-11-29 14:27
337 查看
在java中我们使用多线程去处理一些业务,如果业务比较复杂且当并发量有挺大的时候,很有可能出现线程阻塞的问题。
案例:
有一个触发接口,根据触发的信息内部开启多个线程去执行业务,每个线程都会去执行两种业务:私有业务(比如调用不同的接口)、公共业务(比如执行存储、mq发送等等),当私有业务处理时间很快而公共业务处理时间比较长,这样的情景下就可以把私有业务和公共业务分到不同线程执行。
例如:
当触发了这个接口,根据接口触发的信息,需要开启10个线程,那么就可以创建10个线程去执行它的私有业务,然后再额外创建一个线程去拿到前面那10个线程的执行返回结果并进行公共业务的处理。
这样有个好处,就是能让线程池很快的回收线程,能有效防止线程的阻塞
量化:
单个私有业务1秒钟能执行完成,单个公共业务需要5秒钟才能执行完成,如果接口被触发,发现需要创建100个线程执行,那么线程池回收这些线程池至少需要等待6秒,如果按照前面说的分成两个线程,那么就需要创建101个线程,而1秒后就能回收掉执行完成的100个线程
但是这里需要做权衡,如果接口被触发的时候发现需要开启的线程比较多且公共业务很耗时,这种情况下执行公共业务只有单个线程同步执行,那么这个线程就会执行比较长的时间,所以执行公共业务的时候也可根据实际情况开启多个线程。
下面写了个小demo:
1.私有业务的类:
2.公共业务的类:
3.私有业务的线程类:
4.公共业务的线程类:
6.测试主方法:
执行结果如下:
核心思想: 将多线程的公有的业务抽出来(前提是公有业务比较耗时,不然就没必要了)在其他线程里面执行。
案例:
有一个触发接口,根据触发的信息内部开启多个线程去执行业务,每个线程都会去执行两种业务:私有业务(比如调用不同的接口)、公共业务(比如执行存储、mq发送等等),当私有业务处理时间很快而公共业务处理时间比较长,这样的情景下就可以把私有业务和公共业务分到不同线程执行。
例如:
当触发了这个接口,根据接口触发的信息,需要开启10个线程,那么就可以创建10个线程去执行它的私有业务,然后再额外创建一个线程去拿到前面那10个线程的执行返回结果并进行公共业务的处理。
这样有个好处,就是能让线程池很快的回收线程,能有效防止线程的阻塞
量化:
单个私有业务1秒钟能执行完成,单个公共业务需要5秒钟才能执行完成,如果接口被触发,发现需要创建100个线程执行,那么线程池回收这些线程池至少需要等待6秒,如果按照前面说的分成两个线程,那么就需要创建101个线程,而1秒后就能回收掉执行完成的100个线程
但是这里需要做权衡,如果接口被触发的时候发现需要开启的线程比较多且公共业务很耗时,这种情况下执行公共业务只有单个线程同步执行,那么这个线程就会执行比较长的时间,所以执行公共业务的时候也可根据实际情况开启多个线程。
下面写了个小demo:
1.私有业务的类:
@Component public class Calculation { public Result cal(String req, int a, int b) { System.out.println("请求id:" + req + " 结果:" + (a + b)); return new Result(req, a + b); } }
2.公共业务的类:
@Component public class SomethingElse { public void doElse(Result result) { try { System.out.println(Thread.currentThread().getName() + " : 开始做其他事情,请求号:" + result.getReq() + " ,请求结果:" + result.getSum()); Thread.sleep(2000); System.out.println(Thread.currentThread().getName() + " : 完成做其他事情,请求号:" + result.getReq() + " ,请求结果:" + result.getSum()); } catch (InterruptedException e) { } } }
3.私有业务的线程类:
public class CallTask implements Callable<Result> { private String req; private int a; private int b; @Override public Result call() throws Exception { Calculation calculation = Main.applicationContext.getBean(Calculation.class); return calculation.cal(req, a, b); } public CallTask(String req, int a, int b) { this.req = req; this.a = a; this.b = b; } // getter and setter 等等 }
4.公共业务的线程类:
public class ElseTask implements Runnable { private CompletionService<Result> cs; private int threadCount; public ElseTask(CompletionService<Result> cs, int threadCount) { this.cs = cs; this.threadCount = threadCount; } @Override public void run() { SomethingElse somethingElse = Main.applicationContext.getBean(SomethingElse.class); doElse(somethingElse); } private void doElse(SomethingElse somethingElse) { try { for (int i = 0; i < threadCount; i++) { Future<Result> take = cs.take(); Result result = take.get(); somethingElse.doElse(result); } } catch (Exception e) { } } // getter and setter 等等 }
6.测试主方法:
@Service public class Main implements ApplicationContextAware { public static ApplicationContext applicationContext = null; public static void main(String[] args) throws InterruptedException { AbstractApplicationContext appContext = new ClassPathXmlApplicationContext("application01.xml"); ExecutorService executorService = Executors.newFixedThreadPool(100); CompletionService<Result> cs = new ExecutorCompletionService(executorService); //这里启动执行计算的线程 cs.submit(new CallTask("req001", 0, 1)); cs.submit(new CallTask("req002", 0, 2)); cs.submit(new CallTask("req003", 0, 3)); cs.submit(new CallTask("req004", 0, 4)); cs.submit(new CallTask("req005", 0, 5)); //专门的监控线程,并执行其他耗时的线程 executorService.execute(new ElseTask(cs, 5)); executorService.shutdown(); appContext.registerShutdownHook(); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } }
执行结果如下:
核心思想: 将多线程的公有的业务抽出来(前提是公有业务比较耗时,不然就没必要了)在其他线程里面执行。
相关文章推荐
- Java开发小技巧(四):配置文件敏感信息处理
- Java在处理大数据的时候一些小技巧
- java在处理大数据的时候一些小技巧
- Java小技巧-巧用枚举类型处理判断
- 用Java处理大数据小技巧总结
- java中执行其他程序并处理线程阻塞
- 用Java处理大数据小技巧总结
- Java在处理大数据的时候一些小技巧
- Java在处理大数据的时候一些小技巧
- java在处理大数据的时候一些小技巧
- java并发处理小技巧
- 用Java处理大数据小技巧总结
- 【Java】_处理数据的一些规则及软件开发的一些小技巧和建议
- Java在处理大数据的时候一些小技巧
- Java在处理大数据的时候一些小技巧
- java在处理大数据的时候一些小技巧
- Java在处理大数据的时候一些小技巧
- 【Java学习笔记】52:MouseEvent事件的处理
- kettle调用java代码处理数据
- JAVA学习笔记之异常处理