分布式线程处理

异步线程

1)、继承 Thread

​ Threader01 thread = new Thread010;

​ thread, start();/启动线程

2)、实现 Runnable接口

​ RunabLe01 runabLe01 = new RunabLe010);

​ new Thread(runabLe01)start;

3)、实现 Callable接口+ Future Task(可以拿到返回结果,可以处理异常)

​ FutureTask<Integer) futureTask = new Future Task<>(new CaLLabLe01())

​ new Thread (future Task).start;

​ //阻塞等待整个线程执行完成,获取返回结果

​ Integer integer = futureTask. getO;

4)、线程池

​ 给线程池直接提交任务。

区别

​ 1、2不能得到返回值。3可以获取返回值

​ 1、2、3都不能控制资源

​ 4、可以控制资源,新能稳定

//当前系统中池只有一两个,每个异步任务,提交给线程池让他自己去执行
ExecutorService executorService = Executors.newFixedThreadPool(10);

线程回顾案例

/**
 * @program: gulimall
 * @description: 线程测试类
 * @author: Mr.Lu
 * @create: 2020-08-17 00:28
 **/
public class ThreadTest {
    //当前系统中池只有一两个,每个异步任务,提交给线程池让他自己去执行
    ExecutorService executorService = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {


        System.out.println("main...start......");
        MyThread myThread = new MyThread();
        myThread.start();
        //-----------------------------------------------------
        MyRunable myRunable = new MyRunable();
        new Thread(myRunable).start();
      
      	new Thread(() -> {
            System.out.println("内部Thread当前线程---" + Thread.currentThread().getId());
        }).start();
      
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("内部Runnable当前线程---" + Thread.currentThread().getId());
            }
        }).start();
        //-----------------------------------------------------

        /**
         * 最大的好处,可以返回线程运行的结果
         * 但是是堵塞线程,因为主线程一直要等待Callable运行结束接受值
         */
        FutureTask<Integer> futureTask = new FutureTask<>(new MyCallable());
        new Thread(futureTask).start();
        //阻塞等待整个线程执行完成,获取返回值
        Integer integer = futureTask.get();
        System.out.println("MyCallable的执行结果"+integer);

        /**
         * 这样不好返回结果了
         */
        new Thread(new FutureTask<Integer>(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                int i = 10 / 2;
                System.out.println("内部类的----运行结果" + i);
                return i;
            }
        })).start();
        /**
         * 如果想要拿到结果方式二,不用在建类
         */
        FutureTask<Integer> futureTask1 = new FutureTask<>(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                int i = 10 / 2;
                System.out.println("MyRunable运行结果" + i);
                return i;
            }
        });
        new Thread(futureTask1).start();
        Integer integer1 = futureTask1.get();
        System.out.println("Callable内部类的执行结果"+integer);
        System.out.println("main...end......");

    }

 //-----------------------自己定义类继承方式------------------------------
    public static class MyThread extends Thread {
        @Override
        public void run() {
            System.out.println("MyThread当前线程==" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("MyThread运行结果" + i);
        }
    }

    public static class MyRunable implements Runnable {

        @Override
        public void run() {
            System.out.println("MyRunable当前线程==" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("MyRunable运行结果" + i);
        }
    }


    public static class MyCallable implements Callable<Integer> {

        @Override
        public Integer call() throws Exception {
            System.out.println("MyRunable当前线程==" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("MyRunable运行结果" + i);
            return i;
        }
    }

}

运行结果

main...start......
MyThread当前线程==11
MyThread运行结果5
内部Thread当前线程---12
MyRunable当前线程==13
MyRunable运行结果5
内部Runnable当前线程---14
MyRunable当前线程==15
MyRunable运行结果5
MyCallable的执行结果5
内部类的----运行结果5
MyRunable运行结果5
Callable内部类的执行结果5
main...end......

线程池

给线程池提交任务

//当前系统中池只有一两个,每个异步任务,提交给线程池让他自己去执行
ExecutorService executorService = Executors.newFixedThreadPool(10);
executorService.execute(new Runnable() {
    @Override
    public void run() {
        System.out.println("执行线程");      
    }
});

创建

使用Executor创建线程池

ExecutorService executorService = Executors.newFixedThreadPool(10);
常见的4种线程池

Executors.newCachedThreadPool core是0,所以都可回收

  • 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。

Executors.newFixedThreadPool(值) 固定大小,core=max 都不可回收

  • 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。

Executors.newScheduledThreadPool(size) 做定时任务线程池

  • 创建一个定长线程池,支持定时及周期性任务执行。

Executors.newSingleThreadExecutor 单线程的线程池,后台从队列获取任务,挨个执行

  • 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务

原生线程池

/**
 * 七大参数
 * int corePoolSize,[5] 核心线程数[一直存在];线程池,创建好以后就准备就绪的线程数量,就等待来接受异步任务去执行(除非设置了{@code allowCoreThreadTimeOut})
 * int maximumPoolSize, 最大线程数量;控制资源
 * long keepAliveTime,  存活时间,如果当前的线程数量大于核心corePoolSize数量,
 *                      就释放空闲线程(maximumPoolSize-corePoolSize),只要线程空闲的时间大于指定的keepAliveTime
 * TimeUnit unit,       时间单位
 * BlockingQueue<Runnable> workQueue,  阻塞队列;如果任务有很多,就会将目前多的任务放入到队列中,只要有空闲线程,就去队列中去除新的任务继续执行
 *              ⚠️如果用 new LinkedBlockingDeque<>():默认是integer的最大值,会导致内存不够,所以要指定数量
 * ThreadFactory threadFactory,     线程的创建工厂
 * RejectedExecutionHandler handler 如果队列workQueue满了,按照指定的拒绝策略,拒绝执行任务
 *
 */
        ThreadPoolExecutor executor = new ThreadPoolExecutor(5,
                200,
                10,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(100000),
                Executors.defaultThreadFactory() ,
                new ThreadPoolExecutor.AbortPolicy());
/**
  * 面试题:一个线程池 core7,max20,Queue50,100个并发进来怎么分配
  * 7个会立即执行,50个会进入队列,在开13个进行执行,剩下30个使用拒绝策略
  */

工作流程、

  1. 线程池创建,准备好core数量的核心线程,准备接受任务
  2. 新的任务进来,用core准备好的空闲线程执行。
    1. core满了,就将再进来的任务放入阻塞队列中。空闲的core就会自己去阻塞队列获取任务执行
    2. 阻塞队列满了,就直接开新线程执行,最大只能开到max指定的数量
    3. max都执行好了。 Max-core数量空闲的线程会在 keepAlive Time指定的时间后自动销毀。最终保持到core大小
    4. 如果线程数开到了max的数量,还有新任务进来,就会使用 reject指定的拒绝策略进行处理
  3. 所有的线程创建都是由指定的 factory创建的。

Future可以获取到异步结果

CompletableFuture异步编排

统一解释:

​ 不带Async的就和上一个线程用同一个线程来处理

​ 带Async的将接下来处理是的内容 还是按照 异步线程,交给线程池,让线程池拿一个线程来处理

创建异步线程的四种方法

//不指定线程池
public static CompletableFuture<Void> runAsync(Runnable runnable)
//可以指定线程池
public static CompletableFuture<Void> runAsync(Runnable runnable,Executor executor)
//带返回值 不指定线程池
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)
//带返回值 可以指定线程池
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,Executor executor)

案例

public class ThreadTest {
    //当前系统中池只有一两个,每个异步任务,提交给线程池让他自己去执行
    public static ExecutorService executor = Executors.newFixedThreadPool(10);
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main...start......");
      
//--------------------------------------------------------------
        CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> {
            System.out.println("当前线程==" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("runAsync运行结果" + i);
        }, executor/*交给哪个线程池处理*/);

//--------------------------------------------------------------
        CompletableFuture<Integer> integerCompletableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程==" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("supplyAsync运行结果" + i);
            return i;/*带返回值,可以交给下面的回调方法处理,也可以直接取*/
        }, executor/*交给哪个线程池处理*/);
      	//取值
        Integer integer = integerCompletableFuture.get();
        System.out.println("打印返回值" + integer);
//--------------------------------------------------------------
      
        System.out.println("main...end......");
    }
}

执行结果

main...start......
当前线程==11
runAsync运行结果5
当前线程==12
supplyAsync运行结果5
打印返回值5
main...end......

线程完成时回调感知(CompletableFuture)

//当线程运行成功后,回调什么
//不带Async的就和上一个线程用同一个线程来处理---可以得到线程执行结果,和得到异常信息,但是没办法修改结果
public CompletableFuture<T> whenComplete(BiConsumer<? super T, ? super Throwable> action)
//带Async的将接下来处理是的方式还是按照 异步线程,交给线程池,让线程池拿一个线程来处理
public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action)
public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action, Executor executor)
//详细处理--感知异常,同时返回默认值,如果出现异常了,就返回默认值
public CompletableFuture<T> exceptionally(Function<Throwable, ? extends T> fn)

案例

public class ThreadTest {
    //当前系统中池只有一两个,每个异步任务,提交给线程池让他自己去执行
    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main...start......");

//-------------------------线程回调-------------------------------------
        CompletableFuture<Integer> futureComplete = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程==" + Thread.currentThread().getId());
            int i = 10 / 0;
            System.out.println("MyThread运行结果" + i);
            return i;
        }, executor).whenComplete((result, excption) -> {
            //虽然能得到异常信息,但是没办法修改结果
            System.out.println("异步任务完成了。。。结果是:" + result + ";异常是:" + excption);
        }).exceptionally(throwable -> {
            //感知异常,同时返回默认值
            return 10;
        });
      
//--------------------------------------------------------------
        System.out.println("main...end......");
    }
}

执行结果

main...start......
-------------------------线程回调-------------------------------------
当前线程==13
异步任务完成了。。。结果是:null;异常是:java.util.concurrent.CompletionException: java.lang.ArithmeticException: / by zero
main...end......

handel线程完成后的处理

//可以感知异常,并且可以对结果进行处理返回
public <U> CompletableFuture<U> handle(BiFunction<? super T, Throwable, ? extends U> fn)
public <U> CompletableFuture<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn)
public <U> CompletableFuture<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn, Executor executor)

案例

public class ThreadTest {
    //当前系统中池只有一两个,每个异步任务,提交给线程池让他自己去执行
    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main...start......");
//--------------------------handel------------------------------------
        CompletableFuture<Integer> futureHandel = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程==" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("MyThread运行结果" + i);
            return i;
        }, executor).handle((result, excption) -> {
            System.out.println("异步任务完成了。。。结果是:" + result + ";异常是:" + excption);
            if (result != null) {
                return result * 2;
            }
            if (excption != null) {
                return 0;
            }
            return 0;
        });
      
//--------------------------------------------------------------
        System.out.println("main...end......");
    }
}

执行结果

main...start......
--------------------------handel------------------------------------
当前线程==14
MyThread运行结果5
异步任务完成了。。。结果是:5;异常是:null
main...end......

线程串行化

// A--CompletableFuture的异步任务执行结束了可以 |.thenRun| 接下来继续执行什么 B后续异步任务
  //A-->B,⚠️不可以感知A的执行结果(不呢接收A的返回值,自己也无返回值)
public CompletableFuture<Void> thenRun (Runnable action)
public CompletableFuture<Void> thenRunAsync (Runnable action)
public CompletableFuture<Void> thenRunAsync (Runnable action,Executor executor)


// A--CompletableFuture的异步任务执行结束了可以 |.thenAccept| 接下来继续执行什么 B后续异步任务
	//A-->B,⚠️可以感知A的执行结果(可以拿到A的返回值,自己无返回值)
public CompletableFuture<Void> thenAccept(Consumer<? super T> action)
public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action)
public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action, Executor executor)  


// A--B--C
//A把执行结果给B,B可以感知接收返回值,并且处理后自己在返回一个值给C(可以拿到A的值,自己也带返回值)
public <U> CompletableFuture<U> thenApply(Function<? super T,? extends U> fn)
public <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn) 
public <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn, Executor executor)

案例

public class ThreadTest {
    //当前系统中池只有一两个,每个异步任务,提交给线程池让他自己去执行
    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main...start......");
//--------------------------串行化------------------------------------
        CompletableFuture<Void> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程==" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("future1运行结果" + i);
            return i;
        }, executor).thenApply(future2 -> {
            int i = future2 + 1;
            System.out.println("thenApply运行结果" + i);
            return i;
        }).thenAccept(future3 -> {
            int i = future3 + 1;
            System.out.println("thenAccept运行结果" + i);
        }).thenRun(()->{
            System.out.println("thenRun运行结果:等我其他线程结束,我来做我自己的事情");
        });
      
//--------------------------------------------------------------
        System.out.println("main...end......");
    }
}

执行结果

--------------------------串行化------------------------------------
main...start......
  
当前supplyAsync线程==11
future1运行结果5
  
当前thenApply线程==11
thenApply运行结果6
  
当前thenAccept线程==13
thenAccept运行结果7
  
当前thenRun线程==13
thenRun运行结果:等我其他线程结束,我来做我自己的事情
main...end......

两任务组合–都要完成


//CompletableFuture线程A.runAfterBoth(线程B,线程C)//将A,B组合在一起,运行完了,执行线程C
 ⚠️ //runAfterBoth组合两个线程,不能获取到组合线程的结果
public CompletableFuture<Void> runAfterBoth (CompletionStage < ? > other,Runnable action)
public CompletableFuture<Void> runAfterBothAsync (CompletionStage < ? > other,Runnable action)
public CompletableFuture<Void> runAfterBothAsync (CompletionStage < ? > other,Runnable action,Executor executor)


  
//CompletableFuture线程A.runAfterBoth(线程B,线程C)//将A,B组合在一起,运行完了,执行线程C
  ⚠️//线程C有两个参数,接受A,B任务执行成功的返回值
public <U> CompletableFuture <Void> thenAcceptBoth(CompletionStage < ? extends U > other,BiConsumer < ? super T, ?super U> action)
 
public <U> CompletableFuture <Void> thenAcceptBothAsync(CompletionStage <? extends U> other,BiConsumer <? super T, ?super U> action)
  
public <U> CompletableFuture <Void> thenAcceptBothAsync(CompletionStage <? extends U> other, BiConsumer <? super T, ?super U> action, Executor executor)
 
   
   
//CompletableFuture线程A.runAfterBoth(线程B,线程C)//将A,B组合在一起,运行完了,执行线程C
  ⚠️//线程C有三个参数,接受A,B任务执行成功的返回值,并且自己做处理,返回一个值
public <U, V> CompletableFuture <V> thenCombine(CompletionStage <? extends U> other,BiFunction <? super T,?super U,? extends V> fn)
  
public <U, V> CompletableFuture <V> thenCombineAsync(CompletionStage <? extends U> other,BiFunction <? super T,?super U,? extends V > fn)
  
public <U, V> CompletableFuture <V> thenCombineAsync(CompletionStage <? extends U> other,BiFunction <? super T,?super U,? extends V> fn, Executor executor)
  

案例

public class ThreadTest {
    //当前系统中池只有一两个,每个异步任务,提交给线程池让他自己去执行
    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main...start......");
     //--------------------------两任务组合------------------------------------
        CompletableFuture<Integer> futureCombine = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前任务1线程==" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("任务1运行结果" + i);
            return i;
        }, executor).thenCombineAsync(CompletableFuture.supplyAsync(()->{
            System.out.println("当前任务2线程==" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("任务2运行结果" + i);
            return i;
        }),(result, result2)->{
            System.out.println("当前任务3线程==" + Thread.currentThread().getId());
           int i = result + result2;
            System.out.println("任务2运行结果" + i);
            return i;
        });
      
//--------------------------------------------------------------
        System.out.println("main...end......");
    }
}

执行结果

--------------------------两任务组合------------------------------------
main...start......
  
当前任务1线程==17
任务1运行结果5
  
当前任务2线程==16
任务2运行结果5
  
当前任务3线程==16
任务3运行结果10
main...end......

两任务组合–只要完成一个就执行C

//两个任务A B有一个执行完成,不需要获取 future的结果,处理任务C,也没有返值 
⚠️ //runAfterEither组合两个线程,不能获取到组合线程的结果
public CompletableFuture<Void> runAfterEither(CompletionStage<?> other, Runnable action)
public CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other,Runnable action)
public CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other,Runnable action, Executor executor)


//两个任务A B有一个执行完成,获取它的返回值,处理任务C,没有新的返回值。
⚠️//线程C有一个参数,接受A,B任意一个任务执行成功的返回值
public CompletableFuture<Void> acceptEither(CompletionStage<? extends T> other, Consumer<? super T> action)
public CompletableFuture<Void> acceptEitherAsync(CompletionStage<? extends T> other, Consumer<? super T> action)
public CompletableFuture<Void> acceptEitherAsync(CompletionStage<? extends T> other, Consumer<? super T> action, Executor executor)


//两个任务A B有一个执行完成,获取它的返回值,在任务C处理 并有新的返回值。
 ⚠️//线程C有一个参数,接受A,B任意一个任务执行成功的返回值,并且自己做处理,返回一个值
public <U> CompletableFuture<U> applyToEither(CompletionStage<? extends T> other, Function<? super T, U> fn)
public <U> CompletableFuture<U> applyToEitherAsync(CompletionStage<? extends T> other, Function<? super T, U> fn)
public <U> CompletableFuture<U> applyToEitherAsync(CompletionStage<? extends T> other, Function<? super T, U> fn, Executor executor)

多任务组合

//只要一个任务完成
public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs)
//等待所有任务完成
public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs)
 allOf.get();//⚠️等待所有的结果完成

项目线程池配置

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

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

/**
 * @program: Initialize
 * @description: 线程池配置
 * @author: Mr.Lu
 * @create: 2020-08-17 19:01
 **/
@Configuration
public class MyThreadConfig {
    @Bean
    public ThreadPoolExecutor threadPoolExecutor(ThreadPoolConfigProperties pool) {
        return new ThreadPoolExecutor(
                pool.getCoreSize(),
                pool.getMaxiSize(),
                pool.getKeepAliveTime(),
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(100000),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
    }
}

让他变成可在yml配置的

/**
 * @program: Initialize
 * @description: 线程池的属性配置类
 * @author: Mr.Lu
 * @create: 2020-08-17 19:08
 **/
@ConfigurationProperties(prefix = "thread")
@Component
@Data
public class ThreadPoolConfigProperties {
    /**
     * 核心线程数
     */
    private Integer coreSize;
    /**
     * 最大线程数量
     */
    private Integer maxiSize;
    /**
     * 存活时间
     */
    private Integer keepAliveTime;
}

properties

# 核心线程数
thread.core-size=20
# 最大线程数量
thread.maxi-size=200
# 存活时间
thread.keep-alive-time=10

为了让配置的时候有提示请导入依赖,

        <!--导入配置文件处理器,配置文件进行绑定就会有提示-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值