多线程基础-08

线程池

使用线程池(详细查看JDK文档)

  • 背景:经常创建和销毁、使用量特别大的资源,比如并发情况下的线程,对性能影响很大;
  • 思路:提前创建好多个线程,放入线程池中,使用时直接获取,使用完放回池中。可以避免频繁创建销毁、实现重复利用。类似生活中的公共交通工具;
  • 好处:
    • 提高响应速度(减少了创建新线程的时间)
    • 降低资源消耗(重复利用线程池中的线程,不需要每次都创建)
    • 便于线程管理(…)
      • corePoolSize:核心池的大小
      • maximumPoolSize:最大线程数
      • keepAliveTime:线程没有任务时保持多长时间后会终止
  • JDK 5.0起提供了线程池相关API:ExecutorService和Executors
  • ExecutorService:真正的线程池接口。常见的子类ThreadPoolExecutor
    • void execute(Runnable command):执行任务/命令,没有返回值,一般用来执行Runnable
    • <T> Future<T> submit(Callable<T> task):执行任务,有返回值,一般又来执行Callable
    • void shutdown():关闭连接池;
  • Executors:工具类、线程池的工厂类,用于创建并返回不同类型的线程池

代码实现:没有返回值的(执行Runnable)

// 测试线程池
public class TestThreadExecutor {

    public static void main(String[] args) {
        // 步骤一:创建服务,创建线程池
        //newFixedThreadPool 参数为:线程池的大小
        ExecutorService service = Executors.newFixedThreadPool(10);

        // 步骤二:执行线程
        service.execute(new MyThread());
        service.execute(new MyThread());
        service.execute(new MyThread());
        service.execute(new MyThread());
        service.execute(new MyThread());

        // 步骤三:关闭线程池
        service.shutdown();
    }

}

class MyThread implements Runnable {

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
}

执行结果:

pool-1-thread-1
pool-1-thread-4
pool-1-thread-3
pool-1-thread-2
pool-1-thread-5

代码实现:有返回值Callable<返回值>

// 实现Callable<返回值>()接口--实现多线程下载图片
public class TestCallable implements Callable<Boolean> {//<返回值类型>

    private String url;// 网络图片地址
    private String name;// 保存的文件名

    // 构造器
    public TestCallable(String url,String name){// 构造器是对本类的构造,名字必须一致
        this.url = url;
        this.name = name;
    }

    // 下载图片线程的执行体
    @Override
    public Boolean call() {
        WebDownloader3 webDownloader = new WebDownloader3();
        webDownloader.downloader(url,name);
        System.out.println("下载的文件名为:" + name);
        return true;
    }


    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 图片路径在网上随便找一个
        TestCallable t1 = new TestCallable("https://www.icode9.com/i/ll/?i=48a7e900dbbe409585fe118a293f74df.png","1.jpg");
        TestCallable t2 = new TestCallable("https://www.icode9.com/i/ll/?i=48a7e900dbbe409585fe118a293f74df.png","2.jpg");
        TestCallable t3 = new TestCallable("https://www.icode9.com/i/ll/?i=48a7e900dbbe409585fe118a293f74df.png","3.jpg");

        /*
            1. 开启执行服务:ExecutorService ser = Executors.newFixedThreadPool(1);
            2. 提交执行:Future<Boolean> result1 = ser.submit(t1);
            3. 获取结果:boolean b1 = result1.get();
            4. 关闭服务:ser.shutdownNow();
         */


        // (1)创建执行服务:【ExecutorService与Executors后面详细讲解】
        ExecutorService ser = Executors.newFixedThreadPool(3);

        // (2)提交执行
        Future<Boolean> result1 = ser.submit(t1);
        Future<Boolean> result2 = ser.submit(t2);
        Future<Boolean> result3 = ser.submit(t3);

        // (3)获取结果
        boolean b1 = result1.get();
        boolean b2 = result2.get();
        boolean b3 = result3.get();

        System.out.println(b1);
        System.out.println(b2);
        System.out.println(b3);

        // (4)关闭服务
        ser.shutdownNow();
    }

}

// 下载器
class WebDownloader3{

    // 下载方法
    public void downloader(String url,String name){
        // 使用Commons-io包中的方法进行操作
        try {
            // FileUtils-文件工具
            FileUtils.copyURLToFile(new URL(url),new File(name));// 将网页地址拷贝成文件
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("Io异常,download方法异常!");
        }

    }
}

总结:线程实现的方式

// 总结:线程实现的方式
public class ThreadStyle {

    public static void main(String[] args) {
        // 方式1
        new MyThread1().start();

        // 方式2
        new Thread(new MyThread2()).start();

        // 方式3
        FutureTask<Integer> future = new FutureTask<Integer>(new MyThread3());
        new Thread(future).start();

        try {
            Integer integer = future.get();
            System.out.println("方式3获取的返回值:" + integer);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

}

// 1.继承Thread类
class MyThread1 extends Thread{
    @Override
    public void run() {
        System.out.println("MyThread1");
    }
}

// 2.实现了Runnable接口
class MyThread2 implements Runnable {
    @Override
    public void run() {
        System.out.println("MyThread2");
    }
}

// 3.实现了Callable<V>接口
class MyThread3 implements Callable<Integer> {

    @Override
    public Integer call() throws Exception {
        System.out.println("MyThread3");
        return 520;
    }
}

执行结果:

MyThread1
MyThread2
MyThread3
方式3获取的返回值:520
上一篇:java代理实现


下一篇:Java基础--如何在一个catch中捕获多个异常