龙空技术网

Java之线程详解

阿呆编程 337

前言:

眼前看官们对“java线程详解”都比较注意,大家都想要分析一些“java线程详解”的相关知识。那么小编也在网上收集了一些有关“java线程详解””的相关文章,希望各位老铁们能喜欢,大家一起来了解一下吧!

一:概念

了解线程,得先了解进程。

进程:是具有一定独立功能的程序关于某个数据集合的一次运行活动,它是系统进行资源分配和调度的一个独立单位。

线程:是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。

关系:简而言之,一个程序至少有一个进程,一个进程至少有一个线程。进程和线程的主要差别在于他们是不同的操作系统资源管理方式。

二.创建线程

2.1:设计一个继承java.lang.Thread的子类,覆盖Thread类的run方法。

2.2:设计一个实现Runnable接口的类,实现它的run方法。

启动线程:调用start()方法

运行线程:调用run()方法

三:线程之间的状态

3.1:创建状态:使用new运算符创建一个线程后,该线程处于创建状态。

3.2:就绪状态:用start()方法启动一个线程后,系统为该线程分配除处理机外的所有资源,线程就进入就绪队列排队,等待处理机制调度。

3.3:运行状态:轮到线程占用CPU资源时,JVM将CPU使用权切换给该线程,该线程就可以开始自己的生命周期。

3.4:阻塞状态:正在运行的线程让出CPU使用权,JVM将CPU资源切换给其它线程。阻塞主要有休眠阻塞、等待阻塞、互斥阻塞和其它阻塞等。

3.5:死亡状态:线程运行结束后进入死亡状态。

四:线程的两个特性

多个线程之间是不能直接传递数据交互的,它们之间的交互只能通过共享变量来实现。

线程共享变量的过程:在多个线程之间共享了Count类的一个对象,这个对象是被创建在主内存(堆内存)中,每个线程都有自己的工作内存(线程栈)。操作共享对象时,首先从主内存复制Count对象到工作内存中,修改Count对象,最后用工作内存Count刷新主内存Count。

4.1:可见性

当一个对象在工作内存中都存在副本,一但一个线程修改了共享变量,其他线程能看见修改后的值。

4.2:有效性

多个线程执行时,CPU的调度是随机的。保证线程有序的执行,这就是有效性。

五:线程的同步机制

5.1:synchronized

每个锁对象都有两个队列,分别为就绪队列,阻塞队列。

就绪队列存放了将要获得锁的线程,阻塞队列存放了被阻塞的线程,当一个线程被唤醒后,才会进入就绪队列,等待CPU的调度,反之,进入阻塞队列,等待被唤醒。

一个线程执行互斥代码过程如下:

1. 获得同步锁;

2. 清空工作内存;

3. 从主内存拷贝对象副本到工作内存;

4. 执行代码(计算或者输出等);

5. 刷新主内存数据;

6. 释放同步锁。

5.2:volatile

一个变量可以被volatile修饰,在这种情况下内存模型(主内存和线程工作内存)确保所有线程可以看到一致的变量值

六:线程池

池的最终目的都是节约资源,以更小的开销做更多的事情,从而提高性能。

创建线程池的方式有四种:

6.1. 创建一个可重用固定线程集合的线程池,以共享的无界队列方式来运行这些线程。

ExecutorService threadPool = Executors.newFixedThreadPool(3);

创建了一个固定大小的线程池,容量为3,在FixedThreadPool中,有一个固定大小的池,如果当前需要执行的任务超过了池大小,那么多于的任务等待状态,直到有空闲下来的线程执行任务,而当执行的任务小于池大小,空闲的线程也不会去销毁。

6.2. 创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。

ExecutorService threadPool = Executors.newCachedThreadPool();// 线程池的大小会根据执行的任务数动态分配

CachedThreadPool会创建一个缓存区,将初始化的线程缓存起来,如果线程有可用的,就使用之前创建好的线程,如果没有可用的,就新创建线程。

6.3. 创建一个使用单个 worker 线程的 Executor,以无界队列方式来运行该线程。

ExecutorService threadPool = Executors.newSingleThreadExecutor();

SingleThreadExecutor得到的是一个单个的线程,这个线程会保证你的任务执行完成,如果当前线程意外终止,会创建一个新线程继续执行任务,这和我们直接创建线程不同,也和newFixedThreadPool(1)不同。

6.4. 创建一个可安排在给定延迟后运行命令或者定期地执行的线程池。

ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(3);

ScheduledThreadPool可以定时的或延时的执行任务。

七:锁对象Lock

Lock是java.util.concurrent.locks包下的接口,Lock 实现提供了比使用synchronized 方法和语句可获得的更广泛的锁定操作,它能以更优雅的方式处理线程同步问题.

与synchronized不同:

用sychronized修饰的方法或者语句块在代码执行完之后锁自动释放,而用Lock需要我们手动释放锁,所以为了保证锁最终被释放(发生异常情况),要把互斥区放在try内,释放锁放在finally内。

标签: #java线程详解