java多线程&并发面试108问(中)
2021-01-23 14:14
标签:恢复 框架 epo 线程同步 计算机 调度 stp 互斥 执行 @ 线程相关的基本方法有 wait, notify, notifyAll, sleep, join, yield 等。 调用该方法的线程进入 WAITING 状态,只有等待另外线程的通知或被中断才会返回,需要注意的是调用 wait()方法后, 会释放对象的锁。因此, wait 方法一般用在同步方法或同步代码块中。 sleep 导致当前线程休眠,与 wait 方法不同的是 sleep 不会释放当前占有的锁,sleep(long)会导致线程进入 TIMED-WATING 状态,而 wait()方法会导致当前线程进入 WATING 状态 yield 会使当前线程让出 CPU 执行时间片,与其他线程一起重新竞争 CPU 时间片。一般情况下, 优先级高的线程有更大的可能性成功竞争得到 CPU 时间片, 但这又不是绝对的,有的操作系统对线程优先级并不敏感。 中断一个线程,其本意是给这个线程一个通知信号,会影响这个线程内部的一个中断标识位。 这个线程本身并不会因此而改变状态(如阻塞,终止等)。 join() 方法,等待其他线程终止,在当前线程中调用一个线程的 join() 方法,则当前线程转为阻塞状态,回到另一个线程结束,当前线程再由阻塞状态变为就绪状态,等待 cpu 的宠幸。 很多情况下,主线程生成并启动了子线程,需要用到子线程返回的结果,也就是需要主线程需要在子线程结束后再结束,这时候就要用到 join() 方法 。 Object 类中的 notify() 方法, 唤醒在此对象监视器上等待的单个线程,如果所有线程都在此对象上等待,则会选择唤醒其中一个线程,选择是任意的,并在对实现做出决定时发生,线程通过调用其中一个 wait() 方法,在对象的监视器上等待, 直到当前的线程放弃此对象上的锁定,才能继续执行被唤醒的线程,被唤醒的线程将以常规方式与在该对象上主动同步的其他所有线程进行竞争。类似的方法还有 notifyAll() ,唤醒再次监视器上等待的所有线程。 (有时候也称做任务)是指一个程序运行的实例。在 Linux 系统中,线程就是能并行运行并且与他们的父进程(创建他们的进程)共享同一地址空间(一段内存区域)和其他资源的轻量 级的进程。 是指某一时间点 CPU 寄存器和程序计数器的内容。 是 CPU 内部的数量较少但是速度很快的内存(与之对应的是 CPU 外部相对较慢的 RAM 主内存)。寄存器通过对常用值(通常是运算的中间值)的快速访问来提高计算机程序运行的速度。 是一个专用的寄存器, 用于表明指令序列中 CPU 正在执行的位置,存的值为正在执行的指令的位置或者下一个将要被执行的指令的位置,具体依赖于特定的系统。 上下文切换可以认为是内核(操作系统的核心)在 CPU 上对于进程(包括线程)进行切换,上下文切换过程中的信息是保存在进程控制块(PCB, process control block)中的。 PCB 还经常被称作“切换桢”(switchframe)。 信息会一直保存到 CPU 的内存中,直到他们被再次使用。 当多个线程同时访问同一个数据时,很容易出现问题。为了避免这种情况出现,我们要保证线程同步互斥,就是指并发执行的多个线程,在同一时间内只允许一个线程访问共享数据。 Java 中可以使用 synchronized 关键字来取得一个对象的同步锁。 何为死锁,就是多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。 线程池做的工作主要是控制运行的线程的数量,处理过程中将任务放入队列,然后在线程创建后启动这些任务,如果线程数量超过了最大数量超出数量的线程排队等候,等其它线程执行完毕, 再从队列中取出任务来执行。 他的主要特点为: 线程复用; 控制最大并发数; 管理线程。 每一个 Thread 的类都有一个 start 方法。 当调用 start 启动线程时 Java 虚拟机会调用该类的 run 一般的线程池主要分为以下 4 个组成部分: 线程池中的线程已经用完了,无法继续为新任务服务,同时,等待队列也已经排满了,再也塞不下新任务了。这时候我们就需要拒绝策略机制合理的处理这个问题。 阻塞队列,关键字是阻塞,先理解阻塞的含义,在阻塞队列中,线程阻塞有这样的两种情况: 抛出异常:抛出一个异常; 用数组实现的有界阻塞队列。此队列按照先进先出(FIFO)的原则对元素进行排序。 默认情况下不保证访问者公平的访问队列,所谓公平访问队列是指阻塞的所有生产者线程或消费者线程,当队列可用时,可以按照阻塞的先后顺序访问队列,即先阻塞的生产者线程,可以先往队列里插入元素,先阻塞的消费者线程,可以先从队列里获取元素。通常情况下为了保证公平性会降低吞吐量。我们可以使用以下代码创建一个公平的阻塞队列 基于链表的阻塞队列,同 ArrayListBlockingQueue 类似,此队列按照先进先出(FIFO)的原则对元素进行排序。而 LinkedBlockingQueue 之所以能够高效的处理并发数据,还因为其对于生产者端和消费者端分别采用了独立的锁来控制数据同步,这也意味着在高并发的情况下生产者和消费者可以并行地操作队列中的数据,以此来提高整个队列的并发性能。LinkedBlockingQueue 会默认一个类似无限大小的容量(Integer.MAX_VALUE) 是一个支持优先级的无界队列。默认情况下元素采取自然顺序升序排列。 可以自定义实现 博主公众号程序员小羊 只发面试相关推文 java多线程&并发面试108问(中) 标签:恢复 框架 epo 线程同步 计算机 调度 stp 互斥 执行 原文地址:https://www.cnblogs.com/yn869251541/p/12884325.html
接上一篇文章:上一篇
53、线程基本方法
54、线程等待(wait)
55、线程睡眠(sleep)
56、线程让步(yield)
57、线程中断(interrupt)
InterruptedException,从而使线程提前结束 TIMED-WATING 状态。58、Join 等待其他线程终止
59、为什么要用 join()方法?
System.out.println(Thread.currentThread().getName() + "线程运行开始!");
Thread6 thread1 = new Thread6();
thread1.setName("线程 B"); thread1.join();
System.out.println("这时 thread1 执行完毕之后才能执行主线程");
60、线程唤醒(notify)
61、线程其他方法
62、进程
63、上下文
64、寄存器
65、程序计数器
66、PCB-“切换桢”
67、上下文切换的活动
68、引起线程上下文切换的原因
69、同步锁
70、死锁
71、线程池原理
72、线程复
方法。 那么该类的 run() 方法中就是调用了 Runnable 对象的 run() 方法。 我们可以继承重写
Thread 类,在其 start 方法中添加不断循环调用传递过来的 Runnable 对象。 这就是线程池的实现原理。 循环方法中不断获取 Runnable 是用 Queue 实现的,在获取下一个 Runnable 之前可以是阻塞的 。73、线程池的组成
Java 中的线程池是通过 Executor 框架实现的,该框架中用到了 Executor, Executors, ExecutorService, ThreadPoolExecutor , Callable 和 Future、 FutureTask 这几个类。
ThreadPoolExecutor 的构造方法如下:public ThreadPoolExecutor(
int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue
74、拒绝策略
JDK 内置的拒绝策略如下:
以上内置拒绝策略均实现了 RejectedExecutionHandler 接口,若以上策略仍无法满足实际需要,完全可以自己扩展 RejectedExecutionHandler 接口。75、Java 线程池工作过程
a. 如果正在运行的线程数量小于 corePoolSize,那么马上创建线程运行这个任务;
b. 如果正在运行的线程数量大于或等于 corePoolSize,那么将这个任务放入队列;
c. 如果这时候队列满了,而且正在运行的线程数量小于 maximumPoolSize,那么还是要创建非核心线程立刻运行这个任务;
d. 如果队列满了,而且正在运行的线程数量大于或等于 maximumPoolSize,那么线程池会抛出异常 RejectExecutionException。76、JAVA 阻塞队列原理
阻塞队列的主要方法 :
特殊值:返回一个特殊值(null 或 false,视情况而定) 则塞:在成功操作之前,一直阻塞线程
超时:放弃前只在最大的时间内阻塞
插入操作
public void put(E paramE) throws InterruptedException {
checkNotNull(paramE);
ReentrantLock localReentrantLock = this.lock; localReentrantLock.lockInterruptibly();
try {
while (this.count == this.items.length)
this.notFull.await();//如果队列满了,则线程阻塞等待enqueue(paramE);
localReentrantLock.unlock();
} finally {
localReentrantLock.unlock();
}
}
获取数据操作:
77、Java 中的阻塞队列
78、ArrayBlockingQueue(公平、非公平)
ArrayBlockingQueue fairQueue = new ArrayBlockingQueue(1000,true);
79、LinkedBlockingQueue(两个独立锁提高并发)
80、PriorityBlockingQueue(compareTo 排序实现优先)
compareTo()方法来指定元素进行排序规则,或者初始化 PriorityBlockingQueue 时,指定构造参数 Comparator 来对元素进行排序。需要注意的是不能保证同优先级元素的顺序。扩展连接:更多请点击这里
上一篇:Leetcode练习(Python):动态规划类:第95题:不同的二叉搜索树 II:给定一个整数 n,生成所有由 1 ... n 为节点所组成的二叉搜索树。
下一篇:python 字典按键、值排序
文章标题:java多线程&并发面试108问(中)
文章链接:http://soscw.com/index.php/essay/45916.html