• JDK 5.0 新增解决线程安全 Callable接口和线程池


    在jdk5.0后又新增了两种解决线程安全的问题

     

    一: 实现Callable接口,

    实现接口步骤:

    1: 创建一个实现Callable接口的实现类
    2: 实现Callable接口中的call()方法, 讲此线程需要做的操作声明再这个方法中
    3: 创建Callable 接口实现类的对象
    4: 将创建对象传递到FutureTask构造器中,创建FutureTask对象
    5: 将Future的对象作为参数传递到Thread类中 并调用thread的start()方法
    6: 通过get()获取call方法中的返回值
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.FutureTask;
    
    public class CallableTestTwo {
        public static void main(String[] args) {
            CallableT callableT = new CallableT();  // 3 : 实例化 实现Callable接口的类的对象
            FutureTask futureTask = new FutureTask(callableT);  // 4: 传递此对象到FutureTask 中 并实例化
            new Thread(futureTask).start();  // 5: 生产对象传递到Thread 中并调用start()方法来启动线程
    
            try {  // 6: get获取call方法中抛出的信息  get方法必须搭配try来使用
                Object val = futureTask.get();
                System.out.println("总和是: "+val);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    }
    
    
    class CallableT implements Callable {  // 1: 实现Calable接口
        @Override
        public Object call() throws Exception {  // 2 :实现接口Callable接口中的call()方法
            int num = 0;
            for (int i = 0; i <=  100; i++) {
                System.out.println(i);
                num += i;
            }
            return num;
        }
    }

    如何理解实现Callable接口的方式比创建多线程和实现Runnable接口的方式强大?

    如何理解实现Callable接口的方式比创建多线程和实现Runnable接口的方式强大?
    1: call方法可以有返回值
    2: call方法可以抛出异常被外面的操作捕获, 获取异常信息
    3: Callable是支持泛型的

    二: 线程池

    JDK 5.0起提供了线程池相关API:ExecutorService 和 Executors

    ExecutorService:真正的线程池接口。常见子类ThreadPoolExecutor
    
    Executors:工具类、线程池的工厂类,用于创建并返回不同类型的线程池

    ExecutorService 不能直接手动建立洗澡池子(线程)池子, 需要用工具一个铁湫之类的工具(Executors)来帮助建立线程.

    Executors工具类的方法

     Executors.newCachedThreadPool():创建一个可根据需要创建新线程的线程池
     Executors.newFixedThreadPool(n); 创建一个可重用固定线程数的线程池
     Executors.newSingleThreadExecutor() :创建一个只有一个线程的线程池
     Executors.newScheduledThreadPool(n):创建一个线程池,它可安排在给定延迟后运 行命令或者定期地执行。

    线程池创建的步骤:

    1: ExecutorService 使用工具Executors创建线程池
    2: 得到的对象使用对应线程的方法submit()或者execute() 操作对应线程
    3: shutdown()停止线程

    eg:

    public class ExecutorsTest {
        public static void main(String[] args) {
            // 提供指定线程池的数量
    //        ExecutorService service = Executors.newFixedThreadPool(10);
    
            //
    
            //执行指定的线程的操作,需要提供实现Runnable或者Callable接口的实现的对象
            service.submit();  // 适合使用于Callable
            service.execute();  // 适合适用于Runnable
    
            //关闭线程连接
    //        service.shutdown();
    
    
            ExecutorService executorService = Executors.newFixedThreadPool(10);
    
            executorService.execute(new RunnableT());
            executorService.submit(new RunnableT());
            executorService.shutdown();
    
        }
    }
    import java.util.concurrent.*;
    
    public class CallableTestThree {
        public static void main(String[] args) {
            ExecutorService executorService = Executors.newFixedThreadPool(10);
            RunnableTT runnableTT = new RunnableTT();
            CallableTT callableTT = new CallableTT();
    
            executorService.submit(callableTT); //  submit可以对Callable 和Runnable接口的实现对象进行操作
            executorService.submit(runnableTT);
    
            //executorService.execute(callableTT);  // execute()不可以获取 callable接口的实现对象 因为他只能对Runnable接口的实现对象进行操作
    
            executorService.shutdown();
        }
    
    }
    
    
    
    class RunnableTT implements  Runnable{
        @Override
        public void run() {
            System.out.println("这是取偶数");
            for (int i = 0; i <= 100 ; i++) {
                if(i % 2 == 0){
                    System.out.println(i);
                }
            }
        }
    }
    
    
    
    class CallableTT implements  Callable{
        @Override
        public Object call() throws Exception {
            System.out.println("这是取奇数");
            for (int i = 0; i <= 100 ; i++) {
                System.out.println(i);
            }
            return null;
        }
    }

    Executors工具的操作线程方法一般分为两种

    submit(): 一般操作Callable

    一般主要是操作Callable接口的线程对象, 偶尔可以用于Runnable接口实现的对象,推荐用Callable接口实现的对象

     用来操作实现Callable 接口和Runnable接口的线程对象 , 两者都可以 

    execute():  一般操作Runnable

        只可以操作实现Runnable的接口线程对象

    多线程可以理解为一个公交车 一个人就是线程, 你平时是自己走路快还是坐公交快和便捷呢?

      肯定是坐公交,你不需要管线程池的问题 只需要管你自己就好了, 因为池子可以装多个线程公交可以装多个人

     

  • 相关阅读:
    PHP的strtotime()函数2038年bug问题
    [转]MySQL常用字符串函数
    [转]MySQL日期与时间戳常用函数
    微信公众号开发的一点自我小结,怕自己过后忘了,总结于此。
    [转]去掉IOS下的input 和textarea的内阴影
    [转]Javascript removeChild()删除节点及删除子节点的方法(同样适用于jq)
    能够还原jQuery1.8的toggle的功能的插件
    xp sp3安装.Net 4.0提示严重错误,0x80070643,解决办法2017版
    thinkphp5访问sql2000数据库
    微信网页授权,错误40163,ios正确,安卓错误?
  • 原文地址:https://www.cnblogs.com/zhaoyunlong/p/11887891.html
Copyright © 2020-2023  润新知