多线程

一、线程概念

       进程是正在运行的程序,是系统资源调度的基本单位,一个进程至少有一个线程,线程中可以共享内存资源

      例如:进程执行多件事情,例如一遍听音乐,一遍打游戏,线程是一个事可以分成多线程执行

二、线程创建方式

      ①继承Thread类

      ②实现Ruannable接口

      ③实现Callable接口,可以返回多线程结果

public class CallableImpl implements Callable<Object>{
    @Override
    public Object call() throws Exception {
     // TODO Auto-generated method stub
        System.out.println("多线程:"+Thread.currentThread().getName()+"运行");
        return Thread.currentThread().getName();             
    }
}

public static void main(String[] args) {
        int taskSize = 5;//设置任务数
        //1.创建线程池
        ExecutorService pool = new ThreadPoolExecutor(10,10,60,TimeUnit.SECONDS,new ArrayBlockingQueue<>(10));
        //存储多线程返回值数据
        List<Future> list = new ArrayList<Future>(); 
        for (int i = 0; i < taskSize; i++) {
            // 2.创建callable实现类实例
            CallableImpl thread = new CallableImpl();
            // 3.线程池执行任务 future用来接受多线程返回结果
            Future future = pool.submit(thread);
            list.add(future);
        }
        //4.关闭线程池
        pool.shutdown();
        
        //遍历多线程结果
        for(Future f:list) {
            try {
                System.out.println(f.get());
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ExecutionException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

三、线程池

      在阿里巴巴Java开发手册中提到,避免使用Executors创建线程池,主要是避免使用其中的默认实现,那么我们可以自己直接调用ThreadPoolExecutor的构造函数来自己创建线程池

     正确创建方法:

ExecutorService  executor = new ThreadPoolExecutor(corePoolSize,//核心线程数
                             maximumPoolSize, //最大线程数
                             keepAliveTime,//当线程空闲时,所允许保存的最大时间,超过这个时间,线程将被释放销毁,但只针对于非核心线程。
                             unit,//时间单位,TimeUnit.SECONDS等
                             workQueue,//任务队列
                             threadFactory,//创建线程的工厂类
                             handler//拒绝策略                                                                                                           );

     任务委托给线程池几种方法:

execute(Runnable)//不返回值,如果任务不要求返回值,则选择execute,可以极大提高性能
submit(Runnable)//返回值 submit(Callable)//返回值

    关闭线程池

shutdown()
仅停止阻塞队列中等待的线程,正在执行的线程会执行结束。
shutdownNow()
不仅会停止阻塞队列中的线程,而且会停止正在执行的线程。

    线程池工作原理:

      

四、线程生命周期

五、线程安全问题

          线程安全问题引起原因是多线程资源共享

          解决办法:

         1.使用同步机制,例如synchronized修饰方法或者变量

         2.多线程之间不共享数据,或者共享的数据不做修改

六、线程间通信

      可以通过管道进行线程间通信

七、Future和CompleteableFuture区别    

创建异步操作,runAsync(不支持返回值) 和 supplyAsync方法(支持返回值)
计算结果完成时的回调方法
whenComplete:执行完当前任务的线程,继续执行 whenComplete 的任务。
whenCompleteAsync: 执行完当前任务的线程,把whenCompleteAsync 的任务继续提交给线程池来执行。
exceptionally:当前任务出现异常时,执行exceptionally中的回调方法。
thenApply :当一个线程依赖另一个线程时,可以使用 thenApply 方法来把这两个线程串行化。
handle :是执行任务完成时对结果的处理。
handle 方法和 thenApply 方法处理方式基本一样。不同的是 handle 是在任务完成后再执行,还可以处理异常的任务。thenApply 只可以执行正常的任务,任务出现异常则不执行 thenApply 方法。
thenAccept :消费处理结果,接收任务的处理结果,并消费处理,无返回结果。
thenRun 方法,跟 thenAccept 方法不一样的是,不关心任务的处理结果。只要上面的任务执行完成,就开始执行 thenAccept 。
thenCombine:合并任务,thenCombine 会把 两个 CompletionStage 的任务都执行完成后,把两个任务的结果一块交给 thenCombine 来处理。
thenCompose 方法:thenCompose 方法允许你对两个 CompletionStage 进行流水线操作,第一个操作完成时,将其结果作为参数传递给第二个操作

posted @ 2022-09-20 17:10  远方的风景  阅读(41)  评论(0)    收藏  举报