Fork me on GitHub

Java 线程总结(一)

Java 线程总结(一) —— 线程的基本概念

1、并发:在程序中创建线程来启动多条执行流,从而达到并发。

2、线程:表示一条单独的执行流,它有自己的程序执行计数器,有自己的栈。

3、Java 中有两种创建线程的方式,不管用哪种方式创建线程,都有以下特征:

  • run() 方法是线程执行的主体,run() 方法也是线程执行的入口。线程只会执行 run() 方法里面的语句「包括被 run() 方法调用的语句」。
  • 启动线程必须通过 Thread 对象的 start() 方法进行启动,线程启动以后就会去执行对应的 run() 方法。

4、在多线程中,当所有线程都执行完毕的时候,程序才会退出「这里的线程不包括 daemon 守护线程」。即:当整个程序中剩下的都是 daemo 线程的时候,程序就会退出。

5、Java 中线程有一个优先级的概念,这个优先级会被映射到操作系统中线程的优先级,优先级映射到操作系统中时,到底有没有用,有多大用,都是未知不可控的。优先级对操作系统而言更多的是一种建议和提示,开发中,不要过于依赖优先级。

6、线程的状态
线程的状态

7、什么是守护线程 daemon?
它一般是其他线程的辅助线程,在它辅助的主线程退出的时候,它就没有存在的意义了。例如:在我们运行一个即使最简单的 「hello world」的程序时,实际上,Java 也会创建多个线程,除了 main 线程外,至少还有一个负责垃圾回收的线程,这个线程就是 daemo 线程,在 main 线程结束的时候,垃圾回收线程也会退出。

8、Thread 的 sleep 方法:让当前线程睡眠指定的时间。睡眠期间,线程会让出 cpu,但是不会放弃对象锁

9、Thread 的 yield 方法:让当前线程让出 cup。调用该方法,是告诉操作系统的调度器,我现在不着急占用 CPU,你可以先让其他线程运行。不过这个也仅仅只是建议,调度器如何处理是不一定的。该方法可能会让出 CPU,让出 CPU 后,它自己进入到就绪队列,接着参与下一次的 CPU 竞争,有可能再次拿到 CPU,并且该方法是不释放对象锁的。

10、Thread 的 join 方法:让调用 join 的线程等待该线程结束。

1
2
3
4
5
6
7
8
9
10
11
12
public class Test {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread();
t.start();
/**
* main 线程调用 t.join() 方法
* 即调用 join 的线程是 main 线程
* 即让 main 线程等到 t 线程结束
*/
t.join();
}
}

join 方法的本质是调用了 wait() 方法,由于使用 wait() 方法,那么必定有一个地方在 wait() 所等待的条件满足时,唤醒该线程。这个地方就是:当线程运行结束的时候,Java 系统调用 notifyAll 来通知。

11、在分析代码执行过程时,理解代码在被哪个线程执行是很重要的。要理清执行流、内存和程序代码之间的关系。

12、当多条执行流执行相同的程序代码时,每条执行流都有自己单独的栈,方法中的参数和局部变量都有自己的一份。 当多条执行流可以操作相同的变量时,可能会出现一些意料之外的结果。

13、什么竞态条件?
所谓竞态条件「race condition」是指,当多个线程访问和操作同一个对象时,最终执行结果与执行时序有关,可能正确也可能不正确。

当两个线程竞争同一资源时,如果对资源的访问顺序敏感,就称存在竞态条件。导致竞态条件发生的代码区称作临界区。在临界区中使用适当的同步就可以避免竞态条件。

解决竞态条件的方法有:使用 synchronized 关键字、使用显示锁、使用原子变量。

14、什么是内存可见性问题?
多个线程可以共享访问和操作相同的变量,但一个线程对一个共享变量的修改,另一个线程不一定马上就能看到,甚至永远也看不到。

在计算机系统中,除了内存,数据还会被缓存在 CPU 的寄存器以及各级缓存中,当访问一个变量时,可能直接从寄存器或 CPU 缓存中获取,而不一定到内存中去取,当修改一个变量时,也可能是先写到缓存中,而稍后才会同步更新到内存中。在单线程的程序中,这一般不是个问题,但在多线程的程序中,尤其是在有多 CPU 的情况下,这就是个严重的问题。一个线程对内存的修改,另一个线程看不到,一是修改没有及时同步到内存,二是另一个线程根本就没从内存读。

解决内存可见性的方法有:使用 volatile 关键字、使用 synchronized 关键字、使用显示锁。

15、线程的优点:充分利用多 CPU 的计算能力;充分利用硬件资源;在用户界面「GUI」应用程序中,保持程序的响应性;简化建模及 IO 处理。

16、线程的成本:需要消耗操作系统的资源;需要创建时间;线程调度和切换。

参考博客

Java编程的逻辑——线程的基本概念
Java 线程 Thread.join 方法解析
竞态条件与临界区

-------------本文结束感谢您的阅读-------------

本文标题:Java 线程总结(一)

文章作者:Yan ChongSheng

发布时间:2018年08月14日

最后更新:2018年08月29日

原始链接:yanchongsheng.github.io/2018/08/14/Java-Java-Thread-2018-08-14-Java线程总结-一/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

开启打赏模式