JUC前置知识
JUC概述
在开发语言中,线程部分是重点,JUC是关于线程的。JUC是java.util.concurrent工具包的简称。这是一个处理线程的工具包,JDK1.5开始出现的。
线程和进程
线程和进程的概念
进程(process): 是计算机的程序关于某数据集合上的一次允许活动,是操作系统进行资源分配和任务调度的最小单位,是操作系统的基础。在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令,数据及其组织形式的描述,进程是程序的实体。
线程(thread): 是操作系统或CPU核心能够进行调度的最小单位。被包含在进程中,是进程中的实际运行单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以有多个线程,每个线程执行不同的任务。
总结
进程,是在系统中正在运行的一个应用程序,程序一旦运行就是进程,也是操作系统资源分配的最小单位。
线程,是CPU(Central Processing Unit缩写)核心(现代计算机的CPU可以有多个CPU核心,俗称的4核,8核等)进行资源调度的最小单位,或者说进程内独立执行的一个执行流单元,也是程序执行的最小单位。
线程的状态
线程状态类
- public enum State {
- /**
- * Thread state for a thread which has not yet started.
- */
- //新建
- NEW,
- /**
- * Thread state for a runnable thread. A thread in the runnable
- * state is executing in the Java virtual machine but it may
- * be waiting for other resources from the operating system
- * such as processor.
- */
- //准备就绪,可以运行
- RUNNABLE,
- /**
- * Thread state for a thread blocked waiting for a monitor lock.
- * A thread in the blocked state is waiting for a monitor lock
- * to enter a synchronized block/method or
- * reenter a synchronized block/method after calling
- * {@link Object#wait() Object.wait}.
- */
- //阻塞
- BLOCKED,
- /**
- * Thread state for a waiting thread.
- * A thread is in the waiting state due to calling one of the
- * following methods:
- * <ul>
- * <li>{@link Object#wait() Object.wait} with no timeout</li>
- * <li>{@link #join() Thread.join} with no timeout</li>
- * <li>{@link LockSupport#park() LockSupport.park}</li>
- * </ul>
- *
- * <p>A thread in the waiting state is waiting for another thread to
- * perform a particular action.
- *
- * For example, a thread that has called <tt>Object.wait()</tt>
- * on an object is waiting for another thread to call
- * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
- * that object. A thread that has called <tt>Thread.join()</tt>
- * is waiting for a specified thread to terminate.
- */
- //等待,不见不散
- WAITING,
- /**
- * Thread state for a waiting thread with a specified waiting time.
- * A thread is in the timed waiting state due to calling one of
- * the following methods with a specified positive waiting time:
- * <ul>
- * <li>{@link #sleep Thread.sleep}</li>
- * <li>{@link Object#wait(long) Object.wait} with timeout</li>
- * <li>{@link #join(long) Thread.join} with timeout</li>
- * <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
- * <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
- * </ul>
- */
- //定时等待,过时不候
- TIMED_WAITING,
- /**
- * Thread state for a terminated thread.
- * The thread has completed execution.
- */
- //停止,终止
- TERMINATED;
- }
复制代码 wait和sleep方法的区别
- 1.sleep是Thread类的静态方法,wait是Object类的方法,任何对象实例都能调用。
- 2.sleep不会释放锁,也不需要占有锁。wait会释放锁,但释放锁这个动作的前提是,当前线程占有锁。
- 3.这两个方法都可以被interrupted方法中断。
- 4.这两个方法还有个特点,就是线程在哪里被阻塞,就在哪里被唤醒。
串行,并行和并发
串行模式
串行表示所有任务一一按先后顺序进行。串行意味着必须先装完一车柴才能运送这车柴,只有运送到了,才能卸下这车柴,并且只有完成了这三个步骤,才能进行下一步骤。串行是一次只能取得一个任务,并执行这个任务。
并行模式
并行意味着可以同时取得多个任务,,并同时去执行所取得的这些任务。并行模式相当于将长长的一条队列,划分成了多条短队列,所以并行缩短了任务队列的长度。并行的效率从代码层次上,强依赖于多进程/多线程代码,从硬件角度上依赖于多核CPU。
并发
指的是多个程序可以同时运行的现象,更细化的是多进程可以同时运行或者多指令可以同时运行。
并发的重点是一种现象,描述的是多进程同时运行的现象。但实际上,一个CPU同时,只能运行一个线程。所以同时运行,不是同一时刻有多个线程运行的现象,而是提供一种功能,让用户看起来多个程序同时运行了,但是实际上的线程不是一直霸占CPU的,而是执行一会停,一会执行。
要解决大并发问题,通常是将大任务分解成多个小任务,由于OS(Operating System)对进程的调度是随机的,所以切分成多个小任务后,可能会从任一小任务出执行。可能出现的问题,一个小任务执行了多次,还没开始下个任务。这时一般会采用队列或类似数据结构来存放各个小任务的成果。可能出现还没准备好第一步,就执行第二步的可能。这时,一般采用多路复用或异步的方式,比如只有准备好了,才产生事件执行下一步任务。可以多进程/多线程的方式并行执行这些小任务。也可以单进程/单线程执行这些小任务,这是很可能要配合多路复用才能达到较高的效率。
小结
并发:同一时刻多个线程在访问同一资源,多个线程对一个点。如春运抢票,电商秒杀。
并行:多项工作一起执行,之后再汇总。如泡泡面,水壶烧水,一边放调料。
管程
管程又叫Monitor(监视器),在OS中叫管程/Monitor(监视器),在Java中叫锁(Lock)。
锁其实是一种同步机制,保证同一时间内,只能有一个线程访问受保护的资源。
在JVM中实现这个锁机制(同步机制),是通过进入,退出管程对象实现的,也就是常说的持有锁,和释放锁。进入管程(拥有锁),退出管程(释放锁)。一个线程持有该锁,就只有当前线程可以访问,该锁保护的资源。释放锁,就是当前线程不访问,该锁保护的资源了,其他线程可以竞争该锁,谁获取到锁,可以访问锁保护的线程。
用户线程和守护线程
daemon n.守护神
用户线程和守护线程,是jvm中的概念。
用户线程,顾名思义,用户自定义的线程。主线程结束,用户线程还在运行,jvm存活。
守护线程 ,用于守护用户线程,执行的线程如垃圾回收(gc)。没有用户线程,都是守护线程的化话,主线程结束,jvm结束。设置一个线程为守护线程,必须在开启这个线程之前。- public class Main {
- public static void main(String[] args) {
- Thread thread = new Thread(() -> {
- System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().isDaemon());// aa true
- while(true){
- }
- },"aa");
- thread.setDaemon(true);//通过该方法可将线程设置为守护线程
- thread.start();
- System.out.println(Thread.currentThread().getName() + "over");// mainover
- }
- }
复制代码 只是为了记录自己的学习历程,且本人水平有限,不对之处,请指正。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |