`

Callable在多线程合理优化使用

阅读更多
Future对象在执行使用在外线程中还是同步执行
public class CallableFutureTest {
    ExecutorService executor = Executors.newFixedThreadPool(3);

    @Test
    //@Ignore
    public void testCallable() {
        long start=System.currentTimeMillis();
        try {
            for (int i = 0; i < 5; i++) {
                Callable c = new Callable() {
                    public Object call() throws Exception {
                        Boolean random = new Random().nextBoolean();
                        System.out.println(Thread.currentThread().getName() + "任务启动" + random);
                        Thread.sleep(3000);
                        return random;
                    }
                };
                Future<Boolean> f = executor.submit(c);
                if (!f.get()) {
                    System.out.println("执行continue操作" + f.get());
                    continue;
                }
                System.out.println("执行后插入数据");
            }
            System.out.println("执行时间最后用时-------------------------"+(System.currentTimeMillis()-start));
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        executor.shutdown();
    }
}

执行后的结果用时
Connected to the target VM, address: '127.0.0.1:50960', transport: 'socket'
pool-1-thread-1任务启动true
执行后插入数据
pool-1-thread-2任务启动false
执行continue操作false
pool-1-thread-3任务启动true
执行后插入数据
pool-1-thread-1任务启动false
执行continue操作false
pool-1-thread-2任务启动false
执行continue操作false
执行时间最后用时-------------------------14979

看到前面的调用使用了future并没有体现出他的优势,所以在使用时候调用还是同步,我改进一下调用优化
public class CallableFutureTest {
    ExecutorService executor = Executors.newFixedThreadPool(3);

    @Test
    public void testCallable() {
       long start=System.currentTimeMillis();
        //创建多个线程的返回值
        List<Future> list = Lists.newArrayList();
        try {
            for (int i = 0; i < 5; i++) {
                Callable c = new Callable() {
                    public Object call() throws Exception {
                        Boolean random = new Random().nextBoolean();
                        System.out.println(Thread.currentThread().getName() + "任务启动" + random);
                        Thread.sleep(3000);
                        return random;
                    }
                };
                Future<Boolean> f = executor.submit(c);
                list.add(f);
            }
            for (Future<Boolean> future : list) {
                if (!future.get()) {
                    System.out.println("执行continue操作" + future.get());
                    continue;
                }
                System.out.println("执行后插入数据");
            }
            System.out.println("执行时间最后用时-------------------------"+(System.currentTimeMillis()-start));
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        executor.shutdown();

    }
}

改进后执行后的用时
Connected to the target VM, address: '127.0.0.1:52304', transport: 'socket'
pool-1-thread-1任务启动true
pool-1-thread-2任务启动true
pool-1-thread-3任务启动true
pool-1-thread-3任务启动true
执行后插入数据
执行后插入数据
执行后插入数据
pool-1-thread-2任务启动false
Disconnected from the target VM, address: '127.0.0.1:52304', transport: 'socket'
执行后插入数据
执行continue操作false
执行时间最后用时-------------------------6018


如果在调用时候发生异常情况会怎么样,上边的如果有异常发生会出现消息不能正常处理。看看结果
@Test
    public void testCallable() {
        long start = System.currentTimeMillis();
        //创建多个线程的返回值
        List<Future> list = Lists.newArrayList();

        for (int i = 0; i < 5; i++) {

            Callable c = new Callable() {
                public Object call() throws Exception {
                    Boolean random = new Random().nextBoolean();
                    System.out.println(Thread.currentThread().getName() + "任务启动" + random);
                    Thread.sleep(2000);
                    if (!random) {
                        throw new InterruptedException("执行线程被打断异常");
                    }
                    return random;
                }
            };
            Future<Boolean> f = executor.submit(c);
            list.add(f);
        }
        try {
        for (Future<Boolean> future : list) {

                if (!future.get()) {
                    System.out.println("执行continue操作" + future.get());
                    continue;
                }
                System.out.println("执行后插入数据");

        } } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println("执行时间最后用时-------------------------" + (System.currentTimeMillis() - start));

        executor.shutdown();

    }

抛出异常后的执行结果可以看到只要前面有异常就会阻碍后边的程序执行
pool-1-thread-1任务启动false
pool-1-thread-2任务启动false
pool-1-thread-3任务启动false
pool-1-thread-2任务启动false
pool-1-thread-3任务启动true
执行时间最后用时-------------------------2015
java.util.concurrent.ExecutionException: java.lang.InterruptedException: 执行线程被打断异常
Caused by: java.lang.InterruptedException: 执行线程被打断异常

继续优化异常捕获
@Test
    public void testCallable() {
        long start = System.currentTimeMillis();
        //创建多个线程的返回值
        List<Future> list = Lists.newArrayList();

        for (int i = 0; i < 5; i++) {

            Callable c = new Callable() {
                public Object call() throws Exception {
                    Boolean random = new Random().nextBoolean();
                    System.out.println(Thread.currentThread().getName() + "任务启动" + random);
                    Thread.sleep(2000);
                    if (!random) {
                        throw new InterruptedException("执行线程被打断异常");
                    }
                    return random;
                }
            };
            Future<Boolean> f = executor.submit(c);
            list.add(f);
        }
        for (Future<Boolean> future : list) {
            try {
                if (!future.get()) {
                    System.out.println("执行continue操作" + future.get());
                    continue;
                }
                System.out.println("执行后插入数据");
            } catch (InterruptedException e) {
                System.out.println("-----------------------------执行中途有异常出现InterruptedException");
                e.printStackTrace();
            } catch (ExecutionException e) {
                System.out.println("-----------------------------执行中途有异常出现ExecutionException");
                e.printStackTrace();
            }
        }
        System.out.println("执行时间最后用时-------------------------" + (System.currentTimeMillis() - start));

        executor.shutdown();

    }

看看执行后的日志记录
pool-1-thread-1任务启动false
pool-1-thread-2任务启动true
pool-1-thread-3任务启动true
pool-1-thread-3任务启动true
pool-1-thread-2任务启动false
-----------------------------执行中途有异常出现ExecutionException
执行后插入数据
执行后插入数据
java.util.concurrent.ExecutionException: java.lang.InterruptedException: 执行线程被打断异常
Caused by: java.lang.InterruptedException: 执行线程被打断异常
执行后插入数据
java.util.concurrent.ExecutionException: java.lang.InterruptedException: 执行线程被打断异常
Caused by: java.lang.InterruptedException: 执行线程被打断异常
Disconnected from the target VM, address: '127.0.0.1:55843', transport: 'socket'
-----------------------------执行中途有异常出现ExecutionException
执行时间最后用时-------------------------4028

可以看见执行成功执行的会正常执行完成,想象一下这里我们可以自己处理这些异常,比如将没有执行成功的数据放入消息队列或者放入数据库都可以,等待下次处理或找到调用的问题。

最后版本
@Test
    public void testCallable() {
        long start = System.currentTimeMillis();
        //创建多个线程的返回值
        List<Future> list = Lists.newArrayList();
        for (int i = 0; i < 5; i++) {
            Callable c = new Callable() {
                public Object call() throws Exception {
                    Boolean random = new Random().nextBoolean();
                    System.out.println(Thread.currentThread().getName() + "任务启动" + random);
                    Thread.sleep(2000);
                    if (!random) {
                        throw new InterruptedException("执行线程被打断异常");
                    }
                    return random;
                }
            };
            Future<Boolean> f = executor.submit(c);
            list.add(f);
        }
        for (Future<Boolean> future : list) {
            try {
                if (!future.get()) {
                    System.out.println("执行continue操作" + future.get());
                    continue;
                }
                System.out.println("执行后插入数据成功");
            } catch (InterruptedException e) {
                System.out.println("将异常数据记录到mq或数据库或做补充异步操作-----------------------------执行中途有异常出现InterruptedException");
                continue;
            } catch (ExecutionException e) {
                System.out.println("将异常数据记录到mq或数据库或做补充异步操作-----------------------------执行中途有异常出现ExecutionException");
                continue;
            }
        }
        System.out.println("执行时间最后用时-------------------------" + (System.currentTimeMillis() - start));
        executor.shutdown();//记住这里在使用完后一定要关闭避免引起资源的浪费和死锁
    }


现在我们看看最后的执行效果,看着就很舒服了
Connected to the target VM, address: '127.0.0.1:56951', transport: 'socket'
pool-1-thread-1任务启动true
pool-1-thread-3任务启动false
pool-1-thread-2任务启动false
执行后插入数据
pool-1-thread-1任务启动false
pool-1-thread-3任务启动true
将异常数据记录到mq或数据库或做补充异步操作-----------------------------执行中途有异常出现ExecutionException
将异常数据记录到mq或数据库或做补充异步操作-----------------------------执行中途有异常出现ExecutionException
Disconnected from the target VM, address: '127.0.0.1:56951', transport: 'socket'
将异常数据记录到mq或数据库或做补充异步操作-----------------------------执行中途有异常出现ExecutionException
执行后插入数据
执行时间最后用时-------------------------4013


实际使用中可能会有不同的callable调用,你可以实现自己的callable。

分享到:
评论
1 楼 Janle 2016-12-02  
实际使用中可能会封装对应的多个调用实现接口。

相关推荐

    线程池管理多线程上传

    线程池管理和多线程上传是并发编程中的一个重要实践,特别是在大数据传输和网络服务中。在Java等编程语言中,线程池通过有效地管理和复用线程资源,避免了频繁创建和销毁线程带来的开销,提升了系统性能。下面将详细...

    Android多线程任务优化2:实现后台预读线程

    本篇文章将深入探讨如何通过实现后台预读线程来优化多线程任务,提高用户界面的响应速度和整体应用体验。 首先,了解什么是预读。预读是一种策略,它在用户实际需要数据之前就开始加载,旨在减少等待时间,提高流畅...

    java实现多线程文件传输

    8. **性能调优**:合理设置线程池大小、考虑使用NIO(非阻塞I/O)以减少线程等待时间、监控系统资源使用情况,都是优化多线程文件传输性能的关键。 9. **并发工具类**:`CountDownLatch`、`CyclicBarrier`和`...

    多线程对文件读写操作(java)

    本主题将深入探讨如何使用多线程来优化文件的读取和写入过程,以及需要注意的相关问题。 首先,我们需要理解单线程与多线程在文件操作中的区别。在单线程环境下,文件读写通常是顺序执行的,这意味着如果一个任务...

    java多线程实现大批量数据导入源码

    此外,需要注意的是,多线程环境下可能存在竞态条件、死锁等问题,需要合理使用`synchronized`关键字或`Lock`接口来保证数据的一致性和安全性。另外,适当的错误处理和日志记录也是必不可少的,以确保程序的健壮性。...

    java多线程,对多线程,线程池进行封装,方便使用

    总之,通过合理地封装和使用线程池,开发者可以更好地控制多线程环境,提高系统的稳定性和性能。在实际项目中,我们应该根据具体的需求选择合适的线程池配置,并对其进行监控和调优,确保系统的高效运行。

    多线程的学习资料(对初学者特别有用)!

    在IT领域,多线程是程序设计中的一个重要概念,尤其对于服务器端开发和高并发应用来说,理解并熟练掌握多线程技术至关重要。本资源包针对初学者提供了全面的多线程学习资料,旨在帮助你快速入门并解决实际开发中的...

    SpringBoot版本的多线程下载文件,分段下载文件

    分段下载则是在多线程的基础上,允许用户暂停和恢复下载,提高了用户体验。在SpringBoot中,我们可以通过HTTP协议的`Range`头字段来实现这一功能。当客户端请求文件时,它可以在请求头中包含`Range`字段,如`Range: ...

    多线程读取文件

    在IT领域,多线程是并发处理任务的关键技术,尤其在读取大文件时,能够显著提高程序的执行效率。本文将围绕“多线程读取文件”这一主题,结合给定的标签“源码”和“工具”,深入探讨如何在Java等编程语言中实现这一...

    多线程模型

    3. **数据库连接池**:为了优化数据库连接的创建和释放,可以使用连接池(如C3P0、HikariCP等),它们提供预配置的数据库连接,供多线程共享使用,减少了连接的创建和关闭时间。 4. **事务管理**:多线程环境下,...

    java多线程进阶

    7. **线程性能优化**:如何通过合理的设计和配置来优化多线程程序的性能,例如避免过度同步、减少上下文切换、利用并发容器等。 8. **实战案例**:书中应该会包含一些实际的多线程编程案例,帮助读者将理论知识应用...

    深入学习:Java多线程编程

    4. **并发工具类**:Java的并发包(java.util.concurrent)包含许多高效并发工具,如CountDownLatch、CyclicBarrier、Future和Callable,它们在多线程编程中扮演重要角色。 5. **并发集合**:线程安全的集合类,如...

    JAVA多线程教材

    9. **线程性能调优**:优化多线程程序涉及许多方面,包括合理设置线程数量、避免过度同步、减少上下文切换、使用适当的并发工具等。性能测试和监控也是优化过程的关键部分。 10. **实战案例分析**:通过分析和解决...

    java实现多线程下载文件

    在Java编程中,多线程下载文件是一种优化大文件下载速度和效率的技术。它通过将一个大文件分割成多个小部分,然后同时启动多个线程分别下载这些部分,从而达到加速下载的效果。以下是对这个主题的详细解释: 1. **...

    多线程并发处理数据的问题

    在IT行业中,多线程并发处理数据是一种常见的优化策略,特别是在大数据处理、网络服务和分布式系统中。通过并发,可以充分利用多核处理器的计算能力,提高程序执行效率,缩短任务的总体完成时间。本篇文章将深入探讨...

    java多线程抓取图片

    Java多线程技术在爬虫应用中的重要性不言而喻,它能显著提升图片抓取的效率。本文将深入探讨如何使用Java实现多线程爬虫,以及压缩包中的三个示例案例。 首先,我们需要了解Java中的多线程概念。在Java中,通过创建...

    Java多线程结构_Java多线程结构_

    了解这些状态有助于调试和优化多线程程序。 7. 死锁问题: 当两个或更多线程相互等待对方释放资源时,就会发生死锁。避免死锁的关键是避免循环等待条件和合理设置锁的顺序。 8. 守护线程(Daemon Thread): ...

    多线程编程经典锦集

    多线程性能优化涉及线程池的合理配置、减少上下文切换、避免阻塞操作、使用非阻塞数据结构等。合理的线程数量应考虑系统资源和任务特性,过少可能浪费资源,过多则可能导致上下文切换开销增大。 通过学习《多线程...

    多线程-day01.docx

    在 Java 中,多线程是并发编程的重要概念,它允许程序同时执行多个任务,从而提高系统效率...在后续的学习中,我们将进一步探讨高级多线程技术,如线程池的优化、线程同步机制的使用,以及在实际应用中的秒杀系统实现。

    基于Java的多线程快速排序设计与优化.zip

    在`基于Java的多线程快速排序设计与优化.pdf`文档中,读者可以期待学习到如何使用Java的并发库来实现多线程快速排序,包括线程池的配置、任务的提交、并行度的选择以及优化技巧等。此外,文档可能还会包含实际代码...

Global site tag (gtag.js) - Google Analytics