前言:在面试过程中线程的问题是不可避免的,所以要懂一些线程知识。但是在生活中线程和并发等代码很少去写,因为大部分代码已经封装好了。这篇文章从基础线程讲起。
进程、线程、并发、并行
进程:进程是资源(CPU、内存等)分配的基本单位,它是程序执行时的一个实例。程序运行时系统就会创建一个进程,并为它分配资源,然后把该进程放入进程就绪队列,进程调度器选中它的时候就会为它分配CPU时间,程序开始真正运行。
线程:线程是一条执行路径,是程序执行时的最小单位,它是进程的一个执行流,是CPU调度和分派的基本单位,一个进程可以由很多个线程组成,线程间共享进程的所有资源,每个线程有自己的堆栈和局部变量。线程由CPU独立调度执行,在多CPU环境下就允许多个线程同时运行。同样多线程也可以实现并发操作,每个请求分配一个线程来处理。
一个正在运行的软件(如迅雷)就是一个进程,一个进程可以同时运行多个任务( 迅雷软件可以同时下载多个文件,每个下载任务就是一个线程), 可以简单的认为进程是线程的集合。
线程是一条可以执行的路径。多线程就是同时有多条执行路径在同时(并行)执行
并发:在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行。
就想前面提到的操作系统的时间片分时调度。打游戏和听音乐两件事情在同一个时间段内都是在同一台电脑上完成了从开始到结束的动作。那么,就可以说听音乐和打游戏是并发的。
并行:当系统有一个以上CPU时,当一个CPU执行一个进程时,另一个CPU可以执行另一个进程,两个进程互不抢占CPU资源,可以同时进行,这种方式我们称之为并行。
这里面有一个很重要的点,那就是系统要有多个CPU才会出现并行。在有多个CPU的情况下,才会出现真正意义上的同时进行。
进程、线程、并发三者的关系
进程、线程:进程是CPU,内存等资源占用的基本单位,线程是不能独立占有这些资源的;进程之间相互独立,通信比较困难,线程之间共享一块内存区域,通信方便。一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。线程是操作系统可识别的最小执行和调度单位。线程在执行过程中,需要协作同步。不同进程的线程间要利用消息通信的办法实现同步。资源分配给进程,同一进程的所有线程共享该进程的所有资源。同一进程中的多个线程共享代码段(代码和常量),数据段(全局变量和静态变量),扩展段(堆存储)。但是每个线程拥有自己的栈段,栈段又叫运行时段,用来存放所有局部变量和临时变量,即每个线程都有自己的堆栈和局部变量。
并发、线程:相信大家都知道高并发和多线程的。首先纠正一个误区高并发不等于多线程,多线程是完成任务的一种方法,高并发是系统运行的一种状态,通过多线程有助于系统承受高并发状态的实现。高并发是一种系统运行过程中遇到的一种“短时间内遇到大量操作请求”的情况。就例如淘宝双十一的时候就会出现高并发的情况
线程池
线程池: 线程池就是首先创建一些线程,它们的集合称为线程池。使用线程池可以很好地提高性能,线程池在系统启动时即创建大量空闲的线程,程序将一个任务传给线程池,线程池就会启动一条线程来执行这个任务,执行结束以后,该线程并不会死亡,而是再次返回线程池中成为空闲状态,等待执行下一个任务。
线程池的类型:
1.Executors.newSingleThreadExecutor():创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行
2.Executors.newCacheThreadPool():可缓存线程池,先查看池中有没有以前建立的线程,如果有,就直接使用。如果没有,就建一个新的线程加入池中,缓存型池子通常用于执行一些生存期很短的异步型任务
3.Executors.newFixedThreadPool(int n):创建一个可重用固定个数的线程池,以共享的无界队列方式来运行这些线程
4.Executors.newScheduledThreadPool(int n):创建一个定长线程池,支持定时及周期性任务执行。
其实都是根据需求,也可以自定义线程。
线程的几种状态
新建:当使用new操作符创建新线程时,线程处于“新建“状态
运行(可运行):调用start()方法
阻塞:当线程需要获得对象的内置锁,而该锁正在被其他线程拥有
等待:当线程等待其他线程通知调度表可以运行时
计时等待:对于一些含有时间参数的方法,如Thread类的sleep()
终止:当run()方法运行完毕或出现异常时
如果你不知道当前线程的状态你可以通过Thread类的getState()方法来获取当前线程的状态
线程的优先级
Java中每个线程都有优先级属性,具有较高优先级的线程优先于优先级较低的线程执行,每个线程可能也可能不会被标记为守护进程。当在某个线程中运行创建一个新的 Thread对象时,新的线程的优先级最初设置为等于创建线程的优先级,并且当且仅当创建线程是守护进程时才是守护进程线程。(线程的优先级用数字来表示,范围从1~10,主线程的默认优先级为5
线程中常用到的方法
线程的安全问题
涉及到线程一般都会有主线程和子线程,当线程多的情况下就会出现安全性的问题。多线程安全问题原因是在cpu执行多线程时,在执行的过程中可能随时切换到其他的线程上执行。想要解决这类问题就要涉及到线程的锁了,
synchronized(任意的对象(锁) )
{
写要被同步的代码
}
说到这里就谈谈java的锁,上面的是互斥锁。还有ReentrantLock (顾名思义) :可重入锁,ReentrantReadWriteLock :读写锁。
就到这里吧!写的不好希望大家一起讨论,后期我会出一个二维码建立一个java学习(包括运维)的微信群欢迎大家一起来学习。