Java线程池学习

一、实现Java多线程的方法

1、继承Thread类创建多线程

Thread类本质实现了Runnable接口。启动线程为start0()方法。是个native方法。

 1 public class ThreadProcess extends Thread {
 2 
 3     @Override
 4     public void run(){
 5         long lastTime = System.currentTimeMillis();
 6         for(int i = 0; i < 1; i++){
 7             int ele = Integer.MAX_VALUE;
 8             while (ele >= 0){
 9                 int ele2 = ele - Integer.MAX_VALUE + 65535 - 37666 + 44443;
10                 int temp = Math.max(ele2, ele);
11                 if(temp != ele){
12                     temp = ele;
13                 }
14                 ele = temp-1;
15             }
16         }
17         System.out.println("Time cost from thread " + (System.currentTimeMillis() -  lastTime));
18     }
19 }

2、实现Runnable。一个类已经继承了Thread类就无法继承其它类。

 1 class AccountOperator implements Runnable {
 2     private int count;
 3     private final byte[] lock = new byte[0];
 4 
 5     public AccountOperator() {
 6         this.count = 0;
 7     }
 8 
 9     public void run() {
10         synchronized (lock) {
11             count++;
12             System.out.println(Thread.currentThread().getName() + ":" + count);
13         }
14     }
15 }

3、实现Callable

如果运行完线程并且需要线程返回结果的时候,可以

 1 import java.util.concurrent.Callable;
 2 
 3 public class GetDataThread<V> implements Callable<V> {
 4     private V v;
 5 
 6     public GetDataThread(V v) {
 7         this.v = v;
 8     }
 9 
10     @Override
11     public V call() {
12         return this.v;
13     }
14 }
 1 public class Main {
 2     public static void main(String[] args) throws Exception{
 3         String data = "data";
 4         FutureTask<String> ft = new FutureTask<>(new GetDataCal<>(data));
 5         Thread t = new Thread(ft);
 6         t.start();
 7         String res = ft.get();
 8         System.out.println("Result: " + res);
 9     }
10 }

二、Java线程池

线程的创建和销毁是需要时间的。记线程创建的时间为T1, 线程运行的时间为T2,线程销毁的时间为T3。如果T1 + T3 远远大于 T2,并且有很多这样的任务需要并行执行时,就可以使用线程池。

因为通过线程池,线程资源可以重复使用。

1、常见的线程池

  • newSingleThreadExecutor:创建一个单线程的线程池。这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行
  • newFixedThreadExecutor:创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
  • newCachedThreadExecutor:  创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程可以无限创建。
  • newScheduleThreadExecutor:创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。

2、首先看下ThreadPoolExecutor方法。构造函数包含了几个重要参数,

1     public ThreadPoolExecutor(int corePoolSize,
2                               int maximumPoolSize,
3                               long keepAliveTime,
4                               TimeUnit unit,
5                               BlockingQueue<Runnable> workQueue
6                               RejectedExecutionHandler handler){}
  1. corePoolSize, 线程池核心线程数量
  2. maximumPoolSize,线程池最大线程数
  3. keepAliveTime,当活跃线程数大于核心线程数时,空闲的多余线程最大存活时间
  4. unit  存活时间的单位
  5. workQueue  存放任务的队列
  6. handler  超出线程范围和队列容量的任务的处理程序,也叫拒绝策略。

3、先看下线程池的实现原理

提交一个任务到线程池,线程池的处理流程如下

  • 判断核心线程池是否都在执行任务,如果不是,则创建新的线程执行任务
  • 若核心线程都在执行任务,判断工作队列满没满,如果没满,把任务提交给队列
  • 若队列满了,判断线程池里的线程是否都处于工作状态。如果没有,则创建一个新的工作线程来执行任务,如果满了则交给拒绝策略处理
谢谢!
原文地址:https://www.cnblogs.com/ylxn/p/10354551.html