多线程--线程池

线程池

  • 线程池就是一个可以复用线程的技术
  • 可以控制线程的数量,和存储任务的数量
  • 所以不会因为任务数量过多二创建过多的任务
  • 在JDK5版本中提供了代表线程池的接口ExecutorService,而这个接口下有一个实现类叫ThreadPoolExecutor类,使用ThreadPoolExecutor类就可以用来创建线程池对象。

线程池的注意事项

  • 临时线程什么时候创建
    • 新任务提交时发现核心线程都在忙,任务队列也满了,并且还可以创建新的临时线程,此时才会创建临时线程
  • 什么时候开始拒绝新的任务
    • 核心线程和临时线程都在忙,任务队列也满了,新的任务过来的时候才会开始拒绝任务

一,创建线程池 

1,使用ExecutorService的实现类ThreadPoolExecutor创建线程池对象

多线程--线程池_第1张图片

  • threadFactory 线程工厂
    •  new ArrayBlockingQueue<>(4),一般用这个 4表示可以存储多少个任务
  • 下面代码记住就行直接照搬
    • ExecutorService pool = new ThreadPoolExecutor(
          3,	//核心线程数有3个
          5,  //最大线程数有5个。   临时线程数=最大线程数-核心线程数=5-3=2
          8,	//临时线程存活的时间8秒。 意思是临时线程8秒没有任务执行,就会被销毁掉。
          TimeUnit.SECONDS,//时间单位(秒)
          new ArrayBlockingQueue<>(4), //任务阻塞队列,没有来得及执行的任务在,任务队列中等待
          Executors.defaultThreadFactory(), //用于创建线程的工厂对象
          new ThreadPoolExecutor.CallerRunsPolicy() //拒绝策略
      );

ExecutorService的常用方法 

方法名称

说明

void execute(Runnable command)

执行 Runnable 任务

Future submit(Callable task)

执行 Callable 任务,返回未来任务对象,用于获取线程返回的结果

void shutdown()

等全部任务执行完毕后,再关闭线程池!

List<RunnableshutdownNow()

立刻关闭线程池,停止正在执行的任务,并返回队列中未执行的任务

新任务拒绝策略

策略

详解

ThreadPoolExecutor.AbortPolicy

丢弃任务并抛出RejectedExecutionException异常。是默认的策略

ThreadPoolExecutor.DiscardPolicy:

丢弃任务,但是不抛出异常 这是不推荐的做法

ThreadPoolExecutor.DiscardOldestPolicy

抛弃队列中等待最久的任务 然后把当前任务加入队列中

ThreadPoolExecutor.CallerRunsPolicy

由主线程负责调用任务的run()方法从而绕过线程池直接执行

二,使用线程池执行线程

  •  线程池执行Runnable任务

    • 创建线程类

      • public class MyRunnable implements Runnable{
            @Override
            public void run() {
                // 任务是干啥的?
                System.out.println(Thread.currentThread().getName() + " ==> 输出666~~");
                //为了模拟线程一直在执行,这里睡久一点
                try {
                    Thread.sleep(Integer.MAX_VALUE);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    • 下面是执行Runnable任务的代码

      • ExecutorService pool = new ThreadPoolExecutor(
            3,	//核心线程数有3个
            5,  //最大线程数有5个。   临时线程数=最大线程数-核心线程数=5-3=2
            8,	//临时线程存活的时间8秒。 意思是临时线程8秒没有任务执行,就会被销毁掉。
            TimeUnit.SECONDS,//时间单位(秒)
            new ArrayBlockingQueue<>(4), //任务阻塞队列,没有来得及执行的任务在,任务队列中等待
            Executors.defaultThreadFactory(), //用于创建线程的工厂对象
            new ThreadPoolExecutor.CallerRunsPolicy() //拒绝策略
        );
        
        Runnable target = new MyRunnable();
        pool.execute(target); // 线程池会自动创建一个新线程,自动处理这个任务,自动执行的!
        pool.execute(target); // 线程池会自动创建一个新线程,自动处理这个任务,自动执行的!
        pool.execute(target); // 线程池会自动创建一个新线程,自动处理这个任务,自动执行的!
        //下面4个任务在任务队列里排队
        pool.execute(target);
        pool.execute(target);
        pool.execute(target);
        pool.execute(target);
        
        //下面2个任务,会被临时线程的创建时机了
        pool.execute(target);
        pool.execute(target);
        // 到了新任务的拒绝时机了!
        pool.execute(target);

线程池执行Callable任务

  • 先准备一个Callable线程任务
    • public class MyCallable implements Callable {
          private int n;
          public MyCallable(int n) {
              this.n = n;
          }
      
          // 2、重写call方法
          @Override
          public String call() throws Exception {
              // 描述线程的任务,返回线程执行返回后的结果。
              // 需求:求1-n的和返回。
              int sum = 0;
              for (int i = 1; i <= n; i++) {
                  sum += i;
              }
              return Thread.currentThread().getName() + "求出了1-" + n + "的和是:" + sum;
          }
      }
  • 在测试类中创建线程池,并执行callable任务

    • public class ThreadPoolTest2 {
          public static void main(String[] args) throws Exception {
              // 1、通过ThreadPoolExecutor创建一个线程池对象。
              ExecutorService pool = new ThreadPoolExecutor(
                  3,
                  5,
                  8,
                  TimeUnit.SECONDS, 
                  new ArrayBlockingQueue<>(4),
                  Executors.defaultThreadFactory(),
                  new ThreadPoolExecutor.CallerRunsPolicy());
      
              // 2、使用线程处理Callable任务。
              Future f1 = pool.submit(new MyCallable(100));
              Future f2 = pool.submit(new MyCallable(200));
              Future f3 = pool.submit(new MyCallable(300));
              Future f4 = pool.submit(new MyCallable(400));
      
              // 3、执行完Callable任务后,需要获取返回结果。
              System.out.println(f1.get());
              System.out.println(f2.get());
              System.out.println(f3.get());
              System.out.println(f4.get());
          }
      }

    • 2

你可能感兴趣的:(java,开发语言)