一、实现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){}
- corePoolSize, 线程池核心线程数量
- maximumPoolSize,线程池最大线程数
- keepAliveTime,当活跃线程数大于核心线程数时,空闲的多余线程最大存活时间
- unit 存活时间的单位
- workQueue 存放任务的队列
- handler 超出线程范围和队列容量的任务的处理程序,也叫拒绝策略。
3、先看下线程池的实现原理
提交一个任务到线程池,线程池的处理流程如下
- 判断核心线程池是否都在执行任务,如果不是,则创建新的线程执行任务
- 若核心线程都在执行任务,判断工作队列满没满,如果没满,把任务提交给队列
- 若队列满了,判断线程池里的线程是否都处于工作状态。如果没有,则创建一个新的工作线程来执行任务,如果满了则交给拒绝策略处理