WEB入门浅谈17
多线程
进程是为了实现并发编程的效果,但为了追求更高的效率就引进了线程
创建一个进程和销毁一个进程,开销比较大(进程管理中存在一些系统分配的资源,申请和释放这些资源不是一个容易的事),因此就希望能够更高效,更轻量的完成并发编程。于是就通过线程来完成
线程也被称为 轻量级进程
每个线程就对应到一个 独立的执行流 ,在这个执行流里就可以完成一系列的指令。有多个线程,就对应的有多个执行流,就可以并发的完成多个系列的指令了
一个进程包含了多个线程。一个进程从操作系统中申请了很多资源,进程统一对这些资源进行管理,这个进程内的多个线程,就共享了这些资源。
进程具有 独立性 ,进程与进程之间没有影响(一个进程的创建和销毁不会影响到其它进程)。而线程则不然,如果一个线程出问题了,就可能会影响整个进程的工作。
单进程,单线程:一个人去做一件事。(效率太低)
多进程,单线程:两个人分开去做一件事。(效率提升了,但是资源需要的就多了)
单进程,多线程:两个人一起来做一件事。(效率提升了多余的资源节省了)
创建线程就比创建进程的开销更低
虽然线程越多,效率可能就会越高。但并不是线程越多越好,一旦线程数量太多就会拥挤不堪,多个线程为了争取CPU资源就会造成更多的开销(线程多了,调度的开销也就大了)
要使效率达到最高,那就需要视情况而定创建多少个线程了。例如:
在一台8核CPU的主机上创建进程,那么创建多少个线程就取决于每个线程的执行的任务里,有多少工作是占用CPU,有多少是等待I/O(阻塞)如果线程的工作是纯CPU(无阻塞),那么线程创建8时,效率达到最高。如果线程只有10%占用CPU,那么线程就可以创建到80达到最高效率。(理论)
但是这样做也会出现几个问题,效率虽然高了,开销也小了,但是在工作时,多个线程可能会出现 争抢问题(抢着干一件事,可以理解为分配不均)。也有在工作时,某个线程一直在就绪状态,但是一直轮不上,此时也会出现问题。这个时候就需要考虑线程安全问题。
Java中为了方便操作线程,有Thread这样的类来表示线程
不同的系统上,对于线程这里提供的API是不一样的。Java中都通过Thread类来包装好了
Java中的一个Thread对象就和操作系统内部的一个线程是一一对应的
调用start才是创建新线程,调用run只是一个简单的函数调用
线程的属性
getId()
获取当前线程idgetName()
获取当前线程名称getState()
获取当前线程状态(此处状态指的是Java的线程状态,与操作系统中的进程线程状态类似但不一样)getPriority()
获取当前线程的优先级isDaemon()
查看当前线程是否为守护线程/后台线程
守护线程:主线程(main)结束后,守护线程也不会继续执行了,进程退出,
前台线程:主线程(main)结束后,前台线程继续执行,进程仍然存在isAlive()
判断线程是否结束isInterrupted()
判断线程是否中断
public static Thread currentThread() 获取当前线程对象
public static void sleep(long millis) 休眠
join
join起到的作用是等待某个线程结束
如果在main方法中用t.join() 那么主线程就会进入阻塞状态,等待t线程结束,t线程结束后在运行main方法中join之下的代码。
如果等待的线程已经结束,那么就继续执行下面的代码,就不会进入阻塞状态了
也可以传入一个参数,令主线程等待的超时时间多少ms,如:t.join(1000),那么主线程就会进入阻塞状态等待,最多等待1s。传入两个参数时,第一个参数的单位为ms,第二个参数的单位时ns。
进程和线程
进程包含线程
进程之间是相互隔离的(一个进程的结束不会影响到其它进程的正常工作)
同一个进程的线程之间,共享了一些资源,尤其是内存资源(线程与线程之间,容易互相干扰),一个线程挂了,就有可能导致整个进程都无法工作
进程是系统资源分配和管理的最小单位,线程是调度执行的最小单位
补充
线程与线程之间是共享资源的,而JVM是内存区域划分的。JVM也是一个进程(java进程)JVM在启动的时候会申请一大片内存资源,再把这些资源划分成若干份区域(方法区、堆:多个线程共享的区域。栈、程序计数器:有自己的区域。方法区和堆共享一块区域,其它的都有自己的区域)
但是如果站在操作系统的角度上来看,整个进程的虚拟地址空间,都是由若干个线程来进行共享的
通过代码感受多线程编程
public class Test {
public static void main(String[] args) {
// 虽然此处没有创建线程,但是还是会有一个线程来作为main方法的执行流
System.out.println("多线程");
while (true){
}
}
}
通过jconsole命令观察线程