创建多线程的方式四:使用线程池

说明:
在开发的过程当中,我们不会自己一个一个去造线程,效率太低,开发中用的是线程池
场景: 手机页面是在主线程中加载文本,图片的加载是开辟分线程做的,一个页面会显示很多图片,就意味着要开很多分线程
造线程要花时间,造完线程下载也要花时间,滑动页面时,甚至还没有造好就滑过去了(相当于白造了),所以在滑的过程中CPU,内存消耗比较多
经常创建和销毁、使用量特别大的资源,比如并发情况下的线程, 对性能影响很大。

思路:提前创建好多个线程,放入线程池中,使用时直接获取,使用完放回池中。可以避免频繁创建销毁、实现重复利用

好处:

  • 提高响应速度(减少了创建新线程的时间)
  • 降低资源消耗(重复利用线程池中线程,不需要每次都创建)
  • 便于线程管理 :自己造的线程不便于管理
    corePoolSize:核心池的大小
    maximumPoolSize:最大线程数
    keepAliveTime:线程没有任务时最多保持多长时间后会终止
    还有其他属性
    通过对属性的设置便于对线程更好的进行管理

注意:
放到线程池中的线程只是用完之后还回来了,并不是说线程就被销毁了
用完的线程没有销毁,而是放到线程池中等待重新被利用,降低资源消耗

JDK 5.0起提供了线程池相关API:ExecutorService 和 Executors
ExecutorService:真正的线程池接口,常见子类ThreadPoolExecutor

  • void execute(Runnable command) :执行任务/命令,没有返回值,一般用来执行 Runnable
  • Future submit(Callable task):执行任务,有返回值,一般又来执行 Callable
  • void shutdown() :关闭连接池

Executors:工具类、线程池的工厂类,用于创建并返回不同类型的线程池

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

步骤:

  • 1.提供指定数量的线程池,用ExecutorService进行接收,用Executors.创建并返回相应的线程池
  • 2.提供实现Runnable或者Callable接口的类的对象
  • 3.execute方法适用于实现Runnable接口的
  • 4.submit可以去传一个Callable接口的,注意进行接收FutureTask futuretask=submit(Callable callable),因为返回值为Future
  • 然后用futuretask.get()获取方法的结果
  • 5.关闭连接池

Executors是一个工具类,有很多静态方法
ExecutorService是一个接口,指向的是接口实现类的对象,涉及到多态
这个接口有两个典型的方法,一个叫submit,一个叫execute(参数为Runnable),因为Runnable是重写run方法,run方法又没有返回值,所以execute没有返回值。
对于submit,适合使用Callable,因为参数就是Callable,返回的是Future,execute则适合使用Runnable

package test0;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

    //ExecutorService是接口,就算有属性也是常量,是改不了的,所以要通过接口的实现类来设置线程池的属性
public class ThreadDemo {
    public static void main(String[] args) {
        ExecutorService service = Executors.newFixedThreadPool(10);//按Alt+enter创建相应的对象变量,这里只是说造一个线程池,有这么多线程,但干什么事还要自己指定
        //注意,如果想要设置线程池的属性,要有了线程池之后才可以,所以先要得到service,如果直接Executor.是不现实的

        //怎么知道接口的实现类是谁?用Object中的getClass方法,用来获取对象到底是哪个类
        System.out.println(service.getClass());//结果为类ThreadPoolExecutor

        //那么其实可以考虑进行强制类型转换

        ThreadPoolExecutor service1=(ThreadPoolExecutor)service;

        //通过service1.set之类的进行属性的设置
        service1.setCorePoolSize(15);

        service.execute(new numThread());//会执行传入参数的run方法,是线程池中的一个线程做的


        //执行完之后,如果线程池不用了,可以把线程池关闭

        //service.shutdown();

        //如果还用,并且想让另一个线程作别的事,可以再去造一个实现Runnable接口的实现类,比如numThread1

        service.execute(new numThread1());//并不是说上面那个线程执行完之后才会做这个线程


        service.shutdown();//程序也就停止了


    }
}
class numThread implements Runnable{

    @Override
    public void run() {
        for(int i=0;i<=100;i++){
            if(i%2==0){
                System.out.println(Thread.currentThread().getName()+":"+i);//pool-1-thread-1,表示的是池子里面的线程1
            }
        }
    }
}
class numThread1 implements Runnable{

    @Override
    public void run() {
        for(int i=0;i<=100;i++){
            if(i%2!=0){
                System.out.println(Thread.currentThread().getName()+":"+i);//pool-1-thread-1,表示的是池子里面的线程1
            }
        }
    }
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值