java多线程

多线程

package com.learn.basic.thired.四种创建线程的方式;

import java.util.concurrent.*;

/**
* 1.继承Thread
* 2.实现接口Runnable
* 3.实现接口Callable 之后+FutureTask(可以拿到返回结果,可以处理异常)
* 4.线程池
*/
public class ThreadDemo {
  //创建线程池
  public static ExecutorService service = Executors.newFixedThreadPool(5);

  public static void main(String[] args) throws ExecutionException, InterruptedException {
      /**
       * 1.Thread
       */
      new Thread01().start();
      /**
       * 2.Runnable
       */
      new Thread(new Runnable01()).start();
      /**
       * 3.Callable
       * FutureTask继承关系可以看到,它就是一个Runnable
       */
      FutureTask<Integer> integerFutureTask = new FutureTask<>(new Callable01());
      new Thread(integerFutureTask).start();
      //阻塞等待任务执行完,取任务返回结果
      Integer integer = integerFutureTask.get();
      System.out.println(integer);
      /**
       * 4.线程池本质都是[ExecutorService]
       * 可以执行Runnable,或Callable(当线程池只有一个线程时,可以看到每次用的线程都是同一个)
       */
      service.submit(new Runnable01());
      Future<Integer> submit = service.submit(new Callable01());
      System.out.println(submit.get());
  }

  public static class Thread01 extends Thread {
      @Override
      public void run() {
          System.out.println("线程" + Thread.currentThread().getName());
      }
  }

  public static class Runnable01 implements Runnable {
      @Override
      public void run() {
          System.out.println("线程" + Thread.currentThread().getName());
      }
  }

  /**
   * Callable允许异步任务有返回值
   */
  public static class Callable01 implements Callable<Integer> {
      @Override
      public Integer call() {
          System.out.println("线程" + Thread.currentThread().getName());
          int i = 10 / 2;
          return i;
      }
  }
}
package com.learn.basic.thired;

/**
 * @author 11695
 */
public class ThreadTest {
    /**
     * 多线程卖票的例子,多次运行发现结果有负数(线程安全问题)
     * 解决:在while循环里加上synchronized ()
     * @param args
     */
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            Thread thread = new Thread(new Ticket());
            thread.start();
        }
    }
    static class Ticket implements Runnable {
        private static int i =10;
        @Override
        public void run() {
            while (i>0){
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(i--);
            }

        }
    }
}
package com.learn.basic.thired.线程池;

import java.util.concurrent.*;

/**
 * ThreadPoolExecutor的七大参数
 * int corePoolSize,核心线程数【一直存在】
 * int maximumPoolSize,最大线程数
 * long keepAliveTime,存活时间(线程数 - 核心线程数 = 多余的线程 多余的线程空闲时间大于存活时间,将被释放)
 * TimeUnit unit,存活时间的单位
 * BlockingQueue<Runnable> workQueue,阻塞队列(任务数250>最大线程数50),将未能执行的200个任务放入队列(当线程空闲时就会取队列里的任务),new LinkedBlockingDeque<>(),默认是Integer的最大值。会导致内存不足,最好自己指定
 * ThreadFactory threadFactory,线程的创建工厂(如制定线程的名称)Executors.defaultThreadFactory()默认线程工厂
 * RejectedExecutionHandler handler,阻塞队列满了,按照制定的拒绝策略,拒绝执行任务
 * 拒绝策略:DiscardOldestPolicy丢弃老任务
 *          CallerRunsPolicy不丢弃,同步调用
 *          AbortPolicy直接丢弃新任务,并抛异常
 *          DiscardPolicy直接丢弃新任务,不抛异常
 *
 * <p>
 * 工作顺序:
 * 1.创建线程池,准备core数量的线程
 * 2.core满了,再进来的任务放入阻塞队列
 * 3.阻塞队列满了,开新线程,直到最大线程数
 * 4.最大线程数满了。按照制定的拒绝策略,拒绝执行任务(如果不想拒绝还要执行)
 * 5.任务执行完毕,空闲线程的空闲时间大于存活时间,就释放
 */
public class ThreadPoolDemo {
    public static void main(String[] args) {
        //原生方式new出来
        ThreadPoolExecutor executor = new ThreadPoolExecutor(5,
                200,
                10,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(100000),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
        /**
         * 使用Executors创建常见的4种线程池
         * newCachedThreadPool:核心线程数0,所有线程都可回收,无界队列
         * newFixedThreadPool:固定大小的线程池,核心线程数=最大线程数,所有线程都不可回收,无界队列
         * newScheduledThreadPool:定时任务的线程池,无界队列
         * newSingleThreadExecutor: 核心线程数=最大线程数=1,该线程池只有一个线程,无界队列,队列大小为Integer的最大值
         */
        Executors.newCachedThreadPool();
        Executors.newFixedThreadPool(10);
        Executors.newScheduledThreadPool(10);
        Executors.newSingleThreadExecutor();
    }
}
  • springboot项目中使用配置类配置线程池

package com.learn.mybatis.plus.config;

import org.apache.tomcat.util.threads.ThreadPoolExecutor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;

@Configuration
public class ThreadConfig {
    /**
     * ThreadPoolExecutor创建线程池
     * @return
     */
    @Bean("threadPoolExecutor")
    public ThreadPoolExecutor threadPoolExecutor() {
        ThreadPoolExecutor taskExecutor = new ThreadPoolExecutor(5,
                10,
                10,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(100000),
                Executors.defaultThreadFactory(),
                new java.util.concurrent.ThreadPoolExecutor.AbortPolicy());
        return taskExecutor;
    }

    /**
     * ThreadPoolTaskExecutor 创建线程池
     * 无界队列,最好指定下队列大小,任务太多会内存溢出,线程的最大值也没了意义
     * @return
     */
    @Bean("taskExecutor")
    public AsyncTaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setMaxPoolSize(10);
        taskExecutor.setCorePoolSize(5);
        taskExecutor.setThreadNamePrefix("线程名称");
        taskExecutor.initialize();
        return taskExecutor;
    }
}
  • 异步注解@Async的使用
    springBoot启动类上添加注解@EnableAsync开启异步调用
    在service的实现类里面创建方法,在其他类中调用(本类调用无效同@Transactional,原因spring的动态代理)

/**
* 使用上面创建的线程池 @Async("线程池的名称")
*/
 @Async("threadPoolExecutor")
 public void testAsync() {
      System.out.println(Thread.currentThread().getName());
}
  • ForkJoinPool的使用配合java8并行流parallelStream

package com.learn.basic.thired.forkjoin;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;

public class ForkJoinDemo {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
        ForkJoinPool forkJoinPool = new ForkJoinPool(50);
        ForkJoinTask<?> forkJoinTask = forkJoinPool.submit(() -> {
                    list.parallelStream().forEach(System.out::println);
                }

        );
        forkJoinTask.get();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值