1、继承Thread类
通过继承Thread类,并重写run方法
public class MyThread extends Thread{
public static void main(String[] args) {
MyThread myThread1=new MyThread();
MyThread myThread2=new MyThread();
myThread1.start();
myThread2.start();
}
@Override
public void run() {
super.run();
System.out.println("MyThread.run()");
}
}
2、实现Runnable接口
实现Runnable接口,并重写run方法
public class MyThread1 implements Runnable{
public static void main(String[] args) {
MyThread1 myThread1=new MyThread1();
Thread thread=new Thread(myThread1);
thread.start();
}
@Override
public void run() {
System.out.println("创建多线程--->实现Runnable接口");
}
}
3、实现Callable接口
实现Callable接口,并重写call方法
1、Callable接口有返回值,通过FutureTask可以获取返回值
2、与Runnable接口相比,Callable接口可以抛出异常
public class Mythread2 {
private static Integer Integer;
public static void main(String[] args) {
//1.实例化一个CallableTest对象
CallableTest callableTest=new CallableTest();
//2.实现Callable接口,需要FutureTask实现类的支持,用于接受运算结果
FutureTask futureTask=new FutureTask(callableTest);
//3.将FutureTask的对象作为参数传递到Thread类的构造器中,创建Thread对象,并调用start()
new Thread(futureTask).start();
try {
//4.通过get方法获取结果
Object sum = futureTask.get();
System.out.println("0到100偶数的总和为:"+sum);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
static class CallableTest implements Callable {
@Override
public Integer call() throws Exception {
int sum=0;
for (int i=0;i<=100;i++){
if (i%2==0){
sum+=i;
}
}
return sum;
}
}
}
4、通过线程池的方式实现多线程
java中ThreadPoolExecutor实现多线程的方法
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
参数说明
corePoolSize
核心线程数,核心线程池的大小,当一个任务提交到线程池的时候,核心线程池会创建一个核心线程来执行任务
- 核心线程数会一直存活,即便没有任务需要执行的情况
- 当线程数小于核心线程数时,即便有线程空闲,线程池也会创建新线程处理
- 设置allowsCoreThreadTimeOut=true(默认false)时,核心线程会超时关闭
maximumPoolSize
最大线程数
- 当线程数>=corePoolSize,且任务队列已满时,线程池会创建新线程来处理任务
- 当线程数=maximumPoolSize,且任务队列已满时,线程池会拒绝处理任务而抛出异常
keepAliveTime
线程空闲时间
- 当线程空闲时间达到keepAliveTime时,线程会退出,直到线程数量=corePoolSize
- 如果allowsCoreThreadTimeOut=true,则会知道线程数量=0
TimeUnit
时间单位
BlockingQueue
任务队列
- 核心线程数达到最大时,新任务会放在队列中排队进行等待
RejectedExecutionHandler
拒绝策略,当线程池的队列已经满了的情况下。新进入的任务添加到线程池的时候就会进行处理,JDk默认有四种任务拒绝策略
- AbortPolicy(默认): 默认的拒绝策略,会直接抛出RejectedExecutionException异常
- DiscardPolicy: 当新任务被提交后直接被丢弃
- DiscardOldestPolicy: 当新任务添加进线程池的时候,会放弃任务队列中的头节点,此时丢弃的是队列中存活时间最长的队列
- CallerRunsPolicy: 该策略既不会抛弃任务,也不会抛出异常,而是将任务回推到调用者。"顾名思义,在饱和的情况下,调用者会执行该任务
- 用户自定义拒绝策略: 实现RejectedExecutionHandler,并自己定义策略模式
线程池的执行原理
- 工作流程图如下