你可能已经很熟悉
多任务(multitasking),这是操作系统的一种能力,看起来就可以在同一时刻运行多个程序。例如,在编辑或下载邮件的同时可以打印文件等场景。
一、线程
1.1 什么是线程?
-
线程是程序执行中一个单一的顺序控制流程,是程序执行流的最小单元,是处理器调度和分派的基本单位。 -
一个进程可以有一个或多个线程,各个线程之间共享程序的内存空间(也就是所在进程的内存空间)。
-
一个标准的
线程由线程ID,当前指令指针PC,寄存器和堆栈组成。而进程由内存空间(代码,数据,进程空间,打开的文件)和一个或多个线程组成。
1.2 线程状态:

1.3 线程使用:
/* *
* 实现Runnable接口
* 在run()中编写业务逻辑
*/
public class ThreadSample implements Runnable {
@Override
public void run() {
System.out.println("do something...");
}
public static void main(String[] args) {
ThreadSample threadSample = new ThreadSample();
// 创建线程
Thread thread = new Thread(threadSample);
// 执行
thread.start();
// do something...
}
}
二、进程
2.1 什么是进程?
-
进程是一个具有一定独立功能的程序在一个数据集上的一次
动态执行的过程,是操作系统进行资源分配和调度的一个独立单位,是应用程序运行的载体。 -
进程是一种抽象的概念,从来没有统一的标准定义。
-
进程一般由程序,数据集合和进程控制块三部分组成:
程序用于描述进程要完成的功能,是控制进程执行的指令集;数据集合是程序在执行时所需要的数据和工作区;程序控制块包含进程的描述信息和控制信息是进程存在的唯一标志。
三、线程与进程
3.1 关系:
一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。
资源分配给进程,同一进程的所有线程共享该进程的所有资源。
处理机分给线程,即真正在处理机上运行的是线程。
线程在执行过程中,需要
协作同步。不同进程的线程间要利用消息通信的办法实现同步。线程是指进程内的一个执行单元,也是进程内的可调度实体。
3.2 区别:
线程是程序执行的最小单位,而进程是操作系统分配资源的最小单位;一个
进程由一个或多个线程组成,线程是一个进程中代码的不同执行路线;
进程之间相互独立,但同一进程下的各个线程之间共享程序的内存空间(包括代码段,数据集,堆等)及一些进程级的资源(如打开文件和信号等),某进程内的线程在其他进程不可见;
线程上下文切换比进程上下文切换要快得多。
四、线程安全
当多个线程共享对通用对象的访问时,它们可能彼此
冲突,带来新的bug,程序也会因此受到破坏。
4.1 内部对象锁:
-
概念:它是Java语言内置的一种机制。
-
如果一个方法声明时有
synchronized关键字,那么对象的锁保护整个方法。也就是说,要调用这个方法线程必须获得内部对象锁。 -
使用方式
/* *
* 通过synchronized关键字修饰方法,来进行保护
*/
public synchronized void method(){
// do something...
}
4.2 字段变量同步:
/* *
* 使用volatile关键字使字段同步。
*/
private volatile boolean done;
/* *
* 使用final关键字,安全地访问一个共享变量。
* 如果有多个线程更改和读取这个映射,仍然需要同步。
*/
private final Map<String, Double> accounts = new HashMap<>();
4.3 高效的映射、集和队列:
-
java.util.concurrent包提供了映射、有序集和队列的高效实现。 -
如:
ConcurrentHashMap等… -
这些集合使用复杂的算法,通过允许并发地访问数据结构的不同部分尽可能
减少竞争。
五、线程池
构造一个新的线程开销有些大,因为设计与操作系统地交互。
如果你的程序中创建了大量的生命期很短的线程,那么不应该把每个任务映射到一个单独的线程,而应该使用
线程池。线程池包含许多准备运行的线程。(事先将多个线程对象放到一个容器中,当使用的时候就不用
new线程而是直接去池中拿线程即可)
5.1 :Callable与Future:
-
Runnable封装一个异步运行的任务,Callable<V>与Runnable类似,但是Callable有返回值。 -
Future<V>保存异步计算的结果。
5.2 :常见线程池:
newSingleThreadExecutor:创建一个单线程的线程池,此线程池保证所有任务的执行顺序按照任务的提交顺序执行。
newFixedThreadPool:创建固定大小的线程池,每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。
newCachedThreadPool:创建一个可缓存的线程池,此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。
newScheduledThreadPool:创建一个大小无限的线程池,此线程池支持定时以及周期性执行任务的需求。
newSingleThreadExecutor:创建一个单线程的线程池。此线程池支持定时以及周期性执行任务的需求。
5.3 :线程池优势:
第一:
降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。第二:
提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。第三:
提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。
六、结束语
“-------怕什么真理无穷,进一寸有一寸的欢喜。”
微信公众号搜索:饺子泡牛奶。
1486

被折叠的 条评论
为什么被折叠?



