zoukankan      html  css  js  c++  java
  • 多线程注意事项和获取子线程何时都执行完毕

    前言

    最近一段时间在整公司项目里一个功能的优化,用到了多线程处理。期间也是踩了不少的坑,在这里想说下我遇到的问题和注意事项。以及怎样知道启动的那些多线程都处理完毕这些问题。

    实现Runnable接口类需要注意事项

    我这里用的多线程,是用了实现Runnable接口,这样的话,要比继承Thread类更加的灵活。毕竟类只能单继承,但可以多实现。

    1.事务失效

    我实现Runnable接口的类,是处理业务的handler类,在spring配置里面是默认给这些类添加事务的。所以我当时直接在这个类里面写了业务代码。到测试的时候发现,如果业务方法里报Runtime异常,这个类里面的一些更新方法居然不回滚,直接提交了。

    当时也是试了很多方法,手动给这个类加事务的注解、开辟新事物,都不行。后来查阅资料,发现在Runnable实现类里,是不支持事务的。那我就新写了一个类,把主要的业务方法全放到那个类里,再测试,发现事务可以正常回滚了。

    2.注解无效

    在实现Runnable接口的类里,本来想用spring提供的@Autowired注解来自动注入类呢,发现在run方法里,调用注入的类,报空指针。后来明白,实现Runnable接口的类不受spring监管,所以spring的一些注解就不能使用了。

    解决办法:

    1.可以参考下面这样写,可以获得你想要用的类。

    ApplicationContext ctx = new ApplicationContext();
    ctx.getBean(你想要获取的类名.class);
    

      

    2.那就是在调用多线程实现类之前,在其他类里用spring的一些注解,获得你想要的类,然后通过参数方式,传到多线程实现类里面。(我是采用的这个方式。)

    如何知道多个线程都执行完毕了呢?

    使用多线程,主要就是为了提高程序的运行效率。一般情况下,分配完线程,让那些线程去执行就行了,也不需要关心他们都什么时候执行完毕了。但是有些情况下,知晓那些线程都什么时候执行完毕,确实很有用。

    我实现的那个功能就是放在定时器里面的,知晓定时器什么时候开始,什么时候执行完毕,在完毕的时候执行一些发邮件的一些功能,是很有用的。如果是单线程,那就直接把那些方法日志啥的放到最后执行就可以了。

    但是开辟了多个线程,往往是多线程还在执行,主线程不等那些子线程,就先自己执行完了,这时候,放到最后执行的那些功能就不行了,因为子线程还没执行完,主线程就把最后的那些“收尾”功能给执行了,肯定不合适。

    thread.Join方法,可以让交替执行的线程变成顺序的执行,但这样跟单线程就没啥区别了。

    后来,我想了一个办法。代码如下:

    //线程池
    private ExecutorService threadPool;
    //分配线程任务
    for (int i=0; i<5; i++) {
         threadPool.execute(new RunHandler());
    }
    //关闭线程池,此时执行的线程不会立刻关闭,而是线程池不再接受新的线程请求了,线程执行完会被回收掉。
    threadPool.shutdown();
    while(true){
        if(threadPool.isTerminated()) {//判断线程是否执行完毕,不是就休眠主线程。
            //如果子线程们都执行完毕,就会进这个判断,然后会跳出这个循环。这样就达到了主线程等待子线程们
            //都执行完了,才去执行其他的代码。
            break;
        }
        Thread.sleep(1000);//主线程睡眠1秒
    }
    //这里写执行完毕的日志或者最后的“收尾”功能。
    

      

    这个就是我目前使用的方法。当然,能实现这个功能的方法还有很多,我选的也是比较好实现容易理解,效率算是比较高的一种吧。

    最后

    以上就是我发现和解决的一些常见的问题。由于能力有限,如有错误,敬请谅解。

    写好一个多线程的功能,以上那些注意事项往往根本不够。最主要的是解决多线程之间的冲突,如何避免多线程操作导致变量数据的错乱和引发的数据库保存数据的异常等问题。这些是值得推敲和反复琢磨的,加锁一般能解决这些问题,但是不合理的加锁和使用的加锁方式的不同,可能会导致多线程执行起来的效率不尽人意。

    有时间,我会单独写一篇多线程避免冲突错误的文章,来供大家参考下。

  • 相关阅读:
    函数中的参数说明
    向脚本传递参数
    声明变量类型,数据类型转换
    获取脚本所在目录
    CSV输入输出
    判断计算机是否可以ping通
    REST风格框架:从MVC到前后端分离***
    angularjs + springmvc 上传和下载
    JDBC进行简单的增删改查
    关于有时候导入maven项目时候报错(有红色叹号,类中导入的包提示"the import java.util cannot be resolve,")
  • 原文地址:https://www.cnblogs.com/Simple-Object/p/10740790.html
Copyright © 2011-2022 走看看