实战Java高并发程序设计/第二章 Java并行程序基础 1
2020.8.16开始阅读学习 葛一鸣<<实战Java高并发程序设计>>
第二章 Java并行程序基础
使用多线程而不是多进程进行并发程序的设计 ,线程间的切换和调度成本远远小于进程
2.1线程的基本概念
线程(Thread) 轻量级的进程,程序执行的最小单位
进程(Process) 计算机程序关于某数据集合的一个运行活动,是系统进行资源的分配和调度的基本单位.
程序的概念
程序是指令,数据及组成形式的描述,进程是程序的实体
线程和进程的关系
进程是线程的容器,进程中可以容纳若干线程
说明
在Windows中,后缀为.exe的文件就是程序 ,是静态的,程序是"死的",双击后,指令被加载,会得到一个进程,进程是"活的",程序(进程)开始执行,
在一个进程中.可以包含若干的线程,来执行具体的程序(进程).
2.2.1线程的生命周期

在Thread 类中 定义了一个 枚举类 State 来 定义了 线程的状态(NEW 新建, RUNABLE 就绪, BLOCKED 阻塞, WAITING 等待, TIMED_WAITING有时等待,TERMINATED结束)

public enum State {
NEW,
RUNNABLE,
BLOCKED,
WAITING,
TIMED_WAITING,
TERMINATED;
}
新建状态 Thread t = new Thread();
就绪状态 t.start();
阻塞状态 线程执行中遇到 synchronized
等待状态 WAITING 无时间限制等待 TIMED_WAITING 有时间限制等待
结束状态 线程执行完毕
2.2.2 start()方法和run()方法的区别

start()方法 和 run()方法 都是Thread类的方法 还有一个start0()方法
结合源码注释所述
start()方法是线程执行的原因,JVM会调用run()方法来执行这个线程
结果是两个线程在同时执行,一个执行start()方法,一个执行run()方法
过程中start()方法中会调用start0()方法 (native 修饰的方法) 通知JVM调用run()方法
start()方法 是线程可以执行的标志(开启线程了)
run()方法 是线程执行的具体内容,仅仅Thread.run(),不会开启一个线程,它只是一个普通方法,只会串行的执行run()方法中的代码

Thread类 实现了Runnable接口 重写了run()方法
所以创建线程的方法
一 继承Thread类 重写run()方法
public class myThread extends Thread { @Override public void run() { System.out.println("继承Thread类 创建线程"); } public static void main(String[] args) { myThread myThread = new myThread(); myThread.start(); } }
二 实现Runnable接口 重写run()方法 (Thread类本身也是这么做的,直接实现Runnable接口,避免了重写Thread.run()方法)
说明 在Thread的run方法中 target 就是 Runable实例
Thread的构造方法 也是传入一个Runnable实例 public Thread(Runnable target)
public class myRunnable implements Runnable{ @Override public void run() { System.out.println("实现Runnable接口 创建线程"); } public static void main(String[] args) { Thread thread = new Thread(new myRunnable()); thread.start(); } }
三 实现Callabel接口 重写call()方法
FutureTask task = new FutureTask(new myCallable());
new Thread(task).start();
FutureTask类实现了RunnableFuture接口,RunnableFuture接口继承了Future和Runnable接口。
说明 FutureTask类可以作为Runnable实例 构造一个Thread类


public class myCallable implements Callable { @Override public Object call() throws Exception { StringBuffer buffer = new StringBuffer(); buffer.append("实现Callable接口 "); buffer.append("创建线程"); return buffer.toString(); } public static void main(String[] args) throws Exception { FutureTask<myThread> task = new FutureTask<>(new myCallable()); new Thread(task).start(); System.out.println(task.get()); } }
FutureTask类重写的run()方法 调用了传入的Callabel()接口的call()方法
四 使用线程池创建线程
ExecutorService executorService = Executors.newSingleThreadExecutor();
submit 方法可以接收Runnable Callable实例

public class myThreadPool { public static void main(String[] args) { ExecutorService executorService = Executors.newSingleThreadExecutor(); executorService.submit(new Runnable() { @Override public void run() { System.out.println("线程池创建线程"); } }); executorService.shutdown(); } }