写点什么

多线程实现的方式

作者:jun
  • 2022 年 6 月 10 日
  • 本文字数:1925 字

    阅读完需:约 6 分钟

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,并自己定义策略模式

线程池的执行原理
  • 工作流程图如下(https://gitee.com/ycodingnow/blogimage/raw/master/image/20220609112305.png)

发布于: 刚刚阅读数: 4
用户头像

jun

关注

还未添加个人签名 2021.04.12 加入

IT行业 后端开发

评论

发布
暂无评论
多线程实现的方式_多线程_jun_InfoQ写作社区