栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java多线程、并发(一)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java多线程、并发(一)

进程和线程的关系?区别?
  • 进程是资源分配的最小单位,而线程是 CPU 调度的最小单位;
  • 线程是进程划分成的更小的运行单位,一个进程在其执行的过程中可以产生多个线程。同一个进程中的多个线程之间能够并发执行。
  • 不同进程地址空间相互独立,同一进程内的线程共享同一地址空间。一个进程的线程在另一个进程内是不可见的;
  • 线程执行开销小,但不利于资源的管理和保护;而进程则相反。
  • 在Java中,多个线程共享进程的堆和方法区 (JDK1.8 之后的元空间)资源,但是每个线程有自己的程序计数器、虚拟机栈 和 本地方法栈。
线程创建的方式?
  1. 实现 Runnable 接口;
  2. 实现 Callable 接口;
  3. 继承 Thread 类。
  4. 线程池创建。

实现 Runnable 接口
  • 需要实现 run() 方法。
  • 通过 Thread 调用 start() 方法来启动线程。
public class MyRunnable implements Runnable {
    public void run() {
        // ...
    }
}
public static void main(String[] args) {
    MyRunnable instance = new MyRunnable();
    Thread thread = new Thread(instance);
    thread.start();
}
实现 Callable 接口
  • Callable 可以有返回值,返回值通过 FutureTask 进行封装。
public class MyCallable implements Callable {
    public Integer call() {
        return 123;
    }
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
    MyCallable mc = new MyCallable();
    FutureTask ft = new FutureTask<>(mc);
    Thread thread = new Thread(ft);
    thread.start();
    System.out.println(ft.get());
}

继承 Thread 类
  • 同样也是需要实现 run() 方法,因为 Thread 类也实现了 Runable 接口。
  • 当调用 start() 方法启动一个线程时,虚拟机会将该线程放入就绪队列中等待被调度,当一个线程被调度时会执行该线程的 run() 方法。
public class MyThread extends Thread {
    public void run() {
        // ...
    }
}
public static void main(String[] args) {
    MyThread mt = new MyThread();
    mt.start();
}
Runnable 和 Callable 有什么区别?
  1. Runnable 接口中的 run() 方法的返回值是 void,它做的事情就是去执行 run() 方法中的代码;
  2. Callable 接口中的 call() 方法是有返回值的,和 FutureTask 配合(不会 FutureTask 就不说)可以用来获取执行的结果,也可以抛出异常。
谈谈 synchronized 和 ReentrantLock 的区别
  1. synchronized 是一个关键字,ReentrantLock 是类
  2. synchronized 依赖于 JVM ,而 ReenTrantLock 依赖于 JDK
  3. 相比synchronized,ReentrantLock 更加灵活:
  • 它支持等待可中断,也就是说正在等待的线程可以选择放弃等待,改为处理其他事情。
  • 可以实现公平锁,ReentrantLock 可以指定是公平锁还是非公平锁,而 synchronized 只能是非公平锁
  • 可实现选择性通知,在一个 Lock 对象中可以创建多个 Condition 实例,线程对象可以注册在指定的 Condition  中,从而可以有选择性的进行线程通知

synchronized 关键字就相当于整个 Lock 对象中只有一个 Condition 实例,所有的线程都注册在它一个身上。如果执行 notifyAll()方法的话就会通知所有处于等待状态的线程

而 Condition 实例的 signalAll()方法 只会唤醒注册在该 Condition 实例中的所有等待线程。

说下对线程池的理解?为什么要使用线程池? 

线程池(ThreadPool)是一种基于池化思想来管理和使用线程,它是将多个线程预先存储在一个“池子”内,当有任务出现时,只需要从 线程池 内取出相应的线程执行对应的任务即可。可以避免重新创建和销毁线程所带来性能开销。

使用线程池的优点:

  • 降低资源消耗(通过重复利用已创建的线程降低线程创建和销毁造成的消耗。)
  • 提高响应速度(任务可以不需要等到线程创建就能立即执行。)
  • 便于统一管理线程对象
如何创建线程池?

方式一:通过 ThreadPoolExecutor 的构造方法实现:

public ThreadPoolExecutor(int corePoolSize,
                         int maximumPoolSize,
                         long keepAliveTime,
                         TimeUnit unit,
                         BlockingQueue workQueue,
                         ThreadFactory threadFactory,
                         RejectedExecutionHandler handler) {
                         // 省略相关代码
}

方式二:通过工具类 Executors 来实现

为什么线程池不允许使用Executors去创建? 推荐方式是什么?

推荐通过 ThreadPoolExecutor 的方式去创建。

Executors 创建线程池对象的弊端如下:

  • FixedThreadPool 和 SingleThreadExecutor :允许请求的队列长度为 Integer.MAX_VALUE,可能堆积大量的请求,从而导致 OOM。
  • CachedThreadPool 和 ScheduledThreadPool :允许创建的线程数量为Integer.MAX_VALUE ,可能会创建大量线程,从而导致 OOM。 
线程池核心参数?拒绝策略(饱和策略)? 
public ThreadPoolExecutor(int corePoolSize,
                         int maximumPoolSize,
                         long keepAliveTime,
                         TimeUnit unit,
                         BlockingQueue workQueue,
                         ThreadFactory threadFactory,
                         RejectedExecutionHandler handler) {
                         // 省略相关代码
}

corePoolSize:核心线程数 ,定义了最小可以同时运行的线程数量。

maximumPoolSize:最大线程数,如果队列满了,并且已创建的线程数小于最大线程数,则线程池会再创建新的线程执行任务。

keepAliveTime:线程空闲时的存活时间,就是线程池中除了核心线程之外的其他线程最长可以存活的时间。

unit:keepAliveTime的单位

workQueue:任务队列,用于保存等待执行的任务的阻塞队列。

threadFactory:创建线程的工厂,主要用来创建线程。

handler:拒绝策略,当任务队列满了,且没有空闲的工作线程,如果继续提交任务,必须采取一种策略处理该任务。有四种策略:

  • AbortPolicy:抛出 RejectedExecutionException 异常来拒绝新任务的处理。
  • CallerRunsPolicy:用调用者所在的线程来执行任务。
  • DisCardPolicy:直接丢弃任务。
  • DisCardOldSetPolicy:丢弃阻塞队列中靠最前的任务,并执行当前任务

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1023814.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号