黑马教程强化day4-2

目录

  • 一、线程池
    • 1.线程池定义
    • 2.创建线程池
      • 代码演示
    • 3.通过Executors创建线程池:
      • 代码演示
  • 二、进程
  • 三、并发
  • 四、并行

一、线程池

1.线程池定义

线程池就是一个可以复用线程的技术。
不适用线程池的问题:

  • 用户每发起一个请求,后台就需要创建一个新线程来处理,下次新任务来了肯定又要创建新线程处理的,创建新线程的开销是很大的,并且请求过多时,肯定会产生大量的线程出来,这样会严重印象系统性能。

2.创建线程池

(JDK5提供了代表线程池的接口:ExecutorService)
如何创建线程池对象?

  • 方法一、使用ExecutorsService的实现类ThreadPoolExecutor自创建一个线程池对。
  • 方法二、使用Executors(线程工具类)调用方法返回不同特点的线程池对象。

利用方案一:
ThreadPoolExecutor类提供的构造器(这是一个构造器的七个参数)

  • public ThreadPoolExecutor(int corePoolSize,//指定线程池的核心线程的数量。
  • int maximumPoolSize,//指定线程池的最大线程数量。
  • long keepAliveTime,//指定临时线程的存活时间。
  • TimeUnit unit,//指定临时线程存活的时间单位(秒,分,时,天)
  • BlockingQueue workQueue,//指定线程的任务队列。
  • ThreadFfactory threadFactoty,//指定线程池的线程工厂
  • RejectedExecutionHandler handler )//指定线程池的拒绝策略。

作用:使用治党的初始化参数常见一个新的线程对象。
利用方法二、ExecutorService的常用方法:

  • void execute(Runnable command):执行Runnable任务
  • Future submit(Cakable task):执行Callable任务,并返回Future任务对象,用于获取线程返回的结果
  • void shutdown():等全部任务执行完毕后,再关闭线程
  • List shutdownNow():立刻关闭线程池,停止正在执行的任务,并返回队列中未执行的任务。

线程池的注意事项:

  • 1.什么时候开始创建临时线程?
  • 答:新任务提交时发现核心线程都在忙,任务队列也满了,并且还可以创建临时线程,此时才会创建临时线程。
  • 2.什么时候会拒绝新任务?
  • 答:核心线程和临时线程都在忙,任务队列也满了,新的任务过来的时候才会开始拒绝任务。

任务决绝策略:

  • ThreadPoolExecutor.AbortPolicy():丢弃任务并抛出RejectedExecutionException异常。是默认策略
  • ThreadPoolExecutor.DiscardPolicy():丢弃任务,但是不抛出异常,这是不推荐的做法
  • ThreadPoolExecutor.DiscardOldestPolicy():抛弃队列中等待最久的任务,然后把当前任务加入队列中。
  • ThreadPoolExecutor.CallerRunsPolicy():有主线程负责调用任务的run()方法从而绕过线程池直接执行。

代码演示

主类代码7:

package com.item.Thread6demo;

import java.lang.reflect.Executable;
import java.util.concurrent.*;

public class Threaddemo7 {
    public static void main(String[] args) {
        //1.创建线程池对象来使用
        ExecutorService pool = new ThreadPoolExecutor(3, 5, 10, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(3), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());
        //ThreadPoolExecutor.AbortPolicy():如果对方在忙,则抛会一个异常,不理你。
        //2.使用线程池处理任务,看会不会复用线程?
        Runnable target=new MyRunnable();
        pool.execute(target);//提交第一个任务,创建线程 自动启动线程处理这个任务。
        pool.execute(target);//提交第二个任务
        pool.execute(target);//提交第三个任务
        pool.execute(target);//复用现线程
        pool.execute(target);
        pool.execute(target);
        pool.execute(target);//到了临时线程的创建时机了
        pool.execute( target);//到了临时线程的创建时机了
        pool.execute( target);//到了拒绝策略的时机了,忙不过来。
        //3.关闭线程
        pool.shutdown();//所有任务执行完毕,再关闭线程池。
        pool.shutdownNow();//立即关闭线程池,并停止所有正在执行的任务。
    }
}

主类代码8:

package com.item.Thread6demo;

import java.util.concurrent.*;

public class Threaddemo8 {
    public static void main(String[] args) {
        //1.创建线程池对象来使用
        ExecutorService pool = new ThreadPoolExecutor(3, 5, 10, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(3), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());
        //ThreadPoolExecutor.AbortPolicy():如果对方在忙,则抛会一个异常,不理你。
        //2.使用线程池处理Callable任务。
        Future<String> f1=pool.submit(new MyCallable(100));
        Future<String> f2=pool.submit(new MyCallable(200));
        Future<String> f3=pool.submit(new MyCallable(300));
        Future<String> f4=pool.submit(new MyCallable(400));
        try{
            System.out.println(f1.get());
            System.out.println(f2.get());
            System.out.println(f3.get());
            System.out.println(f4.get());
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

MyRunnable类:

package com.item.Thread6demo;

public class MyRunnable implements Runnable{
@Override
    public void run() {
    for(int i=0;i<5;i++){
        System.out.println(Thread.currentThread().getName()+"输出"+i);
        try {
            Thread.sleep(Integer.MAX_VALUE);//第一个线程打一个零,就睡了,第二个线程一样。
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
}

MyCallable类:

package com.item.Thread6demo;
import java.util.concurrent.Callable;

//1.实现一个callable接口,并实现call方法。
class MyCallable implements Callable<String> {
    private int n;
    public MyCallable(int n){
        this.n = n;
    }
    //2.实现call方法
    public String call() throws Exception{
        int sum = 0;
        for(int i = 0; i < n; i++){
            sum += i;
        }
        return Thread.currentThread().getName()+"计算1-"+n+"的结果"+sum;
    }
}

3.通过Executors创建线程池:

是一个线程的工具类,提供了很多静态方法用于返回不同特点的线程池对象。
方法名称:

  • public static ExecutorService newFixedThreadPool(int nThreads):创建固定线程数量的线程池,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程替代它。
  • public static ExecutorService newSingleThreadExecutor:创建只有一个线程的线程池对象,如果该线程出现异常而结束,那么线程池会补充一个新线程。
  • public static ExecutorService newCachedThreadPool():线程数量随着任务增加而增加,如果线程任务执行完毕且空闲了60s则会被回收掉。
  • public static ScheduledExecutorService newScheduleThreadPool(int corePoolSize):创建一个线程池,可以实现在给定的延迟后运行任务,或者定期执行任务。

Executors使用可能存在的陷阱(学黑马的课程有时候经典白学,用作了解)

  • 1.大型并发系统环境中使用Executors如果不注意可能会出现系统风险。
  • (阿里巴巴推荐使用ThreadPoolExecutor的七个参数来创建。

代码演示

package com.item.Thread7demo;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Threaddemo9 {
    public static void main(String[] args) {
        ExecutorService pool = Executors.newFixedThreadPool(3);
    }
}

二、进程

进程:正在运行的程序(软件)就是一个独立的进程。

  • 线程是属于进程的,一个进程中可以同时运行很多个线程
  • 进程中的多个线程其实可以是并发和并行执行的。

三、并发

并发的含义:并发(Concurrency)指的是系统在同一时间段内处理多个任务的能力。并发关注的是任务之间的交替执行,任务之间可能并不真正同时运行,而是通过任务的分时调度机制,使得多个任务在时间上交错进行,从而给用户一种“同时”执行的感觉。

四、并行

并行的含义:并行(Parallelism)指的是系统同时执行多个任务的能力。并行是指在多个处理器或多核处理器上,真正同时地运行多个任务。并行化的目标是提高程序的执行效率,特别是在需要处理大量数据或计算密集型任务时,并行化可以显著减少任务的完成时间。

你可能感兴趣的:(java_up,java,开发语言)