Java并发编程详解读书笔记(一)
一、线程介绍
讲线程之前得先了解进程(Peocess),现在的操作系统基本都支持多任务的进行,举个场景:有许多的程序员们喜欢边coding边听点轻音乐。这时计算机就是做并行任务,也就是有多个进程在同时进行。进程是一个具有独立功能的程序在数据集合上的一次执行过程,简言之一个进程就是一个应用程序,进程是系统进行资源分配和调度的基本单位,而一个进程至少包含一个线程(Thread),线程是进程中
的一个执行单位或执行实体,只拥有少量资源,线程也成为轻量级进程,线程是处理机(Java中为JVM)调度和分配的基本单位。
总结:
- 进程是系统进行资源调度和分配的基本单位
- 线程是处理机进行调度和分配的基本单位
- 一个进程至少包含有一个线程(包含关系)
- 操作系统中进程的创建与撤销开销大于线程
了解了线程的概念后我们来简单实现下边coding边听音乐:
public class TryConcurrency { public static void coding() throws InterruptedException { while(true) { System.out.println("I am coding.."); Thread.sleep(1000); } } public static void listening() throws InterruptedException { while(true) { System.out.println("I am listening music.."); Thread.sleep(1000); } } public static void main(String[] args) { try { coding(); listening(); } catch (InterruptedException e) { e.printStackTrace(); } } }
执行后结果为:
该结果为一直coding,并没有向我们预期那样交替执行,我们知道Java se 程序的入口为main方法,当main方法启动后,JVM进程会分配一个main线程来执行,main线程执行是自上而下的,故执行到
coding()方法是就陷入了无限循环中无法返回,故listening()方法编程了unreachable 代码,即不可达代码。我们要想让listening方法也执行就需要再使用一个线程类Thread,让两个方法“并行”执行:
public static void main(String[] args) { new Thread() { @Override public void run() { try { listening(); } catch (InterruptedException e) { e.printStackTrace(); } } }.start(); try { coding(); } catch (InterruptedException e) { e.printStackTrace(); } }
再来看看结果:
从结果中我们可以看到达到了我们的预期。
二、线程的生命周期
线程总共有五个生命周期,分别为:new,runnable,running,blocked,terminated。翻译为中文即:创建状态,就绪/可执行状态,运行状态,阻塞状态,终止状态。
现在来以此说说这些状态,首先Thread t = new Thread()后该线程t就是为创建状态,而后再调用start()方法后进入就绪状态等待处理机进行调度,处理机通过轮询等方式后
就可以进入执行状态,在执行状态中以下操作会使线程进入阻塞状态:
- 主动调用sleep,wait方法后进入waitSet中进入阻塞状态
- 进入某个阻塞的IO操作,比如因网络数据的读写而进入阻塞状态
- 获取某个锁资源,从而加入到该锁的阻塞队列中进入阻塞状态
线程的以下情况会使其进入terminated:
- 线程运行正常结束,结束生命周期
- 线程运行出错意外结束
- JVM crash 导致所有线程都结束
三、start方法介绍分析
我们在创建Thread线程的时候需要重写run方法,并调用start方法来启动线程。那么run方法和start方法有什么关联呢?
阅读start源码就可以知道,首先它是判断threadStatus这个属性是否为0,为0才可以继续否则抛异常,然后再调用start0这个JNI方法,也就是本地方法。
深入分析后可以得知,线程进入执行状态之后JVM执行run方法中的执行体。 阅读玩start源码可以有以下总结:
- 由于首先判断threadStatus属性是否为0,可知再new Thread后初值为0,而后变化。故不可进行二次start。
- 一个线程执行结束,也就是到了terminated状态后,不可以再调用start方法。