java多线程详解(一)

Bertha 。 2022-07-17 00:16 307阅读 0赞

一、概念

1、进程:是指一个内存中运行的应用程序。

每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程。

比如,在windows系统中,一个运行的exe就是一个进程。

2、线程:是进程中的一个执行流程,一个进程中可以运行多个线程。

比如:java.exe进程中可以运行多个线程。

线程总是属于某一个进程的,进程中的多个线程共享进程的内存。

注:所谓的“同时”,实际上是多个线程之间轮流执行的结果,只不过每个线程执行的时间很短,就切换到另一个线程,人眼看起来像是同时在执行。

二、java中线程

1、使用Thread类或者Runnable接口 来定义、实例化和启动新线程。

2、一个Thread类实例是一个对象,具有变量和方法,存放在堆内存中。

3、每个线程都有一个调用栈,一旦创建一个新线程,就会产生一个新的调用栈。

线程的创建和启动

一、实例化线程

a) 扩展java.lang.Thread类,如:

  1. package com;
  2. public class MyThread extends Thread {
  3. public MyThread(String name) {
  4. super(name) ;
  5. }
  6. @Override
  7. public void run() {
  8. for (int i = 0; i < 5; i++) {
  9. for (int j = 0; j < 10; j++) {
  10. System.out.println(this.getName()+" : "+i);
  11. }
  12. }
  13. }
  14. public static void main(String[] args) {
  15. Thread t1 = new MyThread("张三") ;
  16. Thread t2 = new MyThread("李四") ;
  17. t1.start();
  18. t2.start();
  19. }
  20. }

a) 实现java.lang.Runnable接口

  1. package com;
  2. public class MyRunnable implements Runnable {
  3. private String name ;
  4. public MyRunnable(String name) {
  5. this.name = name ;
  6. }
  7. public void run() {
  8. for (int i = 0; i < 5; i++) {
  9. for (int j = 0; j < 10; j++) {
  10. System.out.println(name +" : "+i);
  11. }
  12. }
  13. }
  14. public static void main(String[] args) {
  15. Thread t1 = new Thread(new MyRunnable("张三")) ;
  16. Thread t2 = new Thread(new MyRunnable("李四")) ;
  17. t1.start();
  18. t2.start();
  19. }
  20. }

一、启动线程

a) 在线程的Thread方法上,调用start()方法,不是run()方法

b) 在调用start()方法前:

  1. i. 线程处于新状态,新状态指有一个Thread对象,但还并不是一个真正的线程。

c) 在调用start()方法后:

  1. i. 发生如下变化:
  1. 启动新的执行线程(具有新的调用栈)

  2. 该状态从新状态转移到可执行状态

  3. 当该线程获得机会执行时,其目标run()方法将运行

注:对于java来说,run()方法就像main()方法一样,只是新线程知道调用的方法名称和签名,

因此,在Runnable上或者Thread上调用run方法是合法的,但并不启动新的线程。

二、线程模型和线程调度原理

a) 线程栈模型

  1. i. 线程模型是理解线程调度原理以及线程执行过程的基础。
  2. ii. 线程栈:是指某一个时刻内存中线程调度的栈信息,当前正在调用的方法总是位于栈顶,线程栈中的内容是随着线程的运行状态变化而变化的,我们要研究线程栈,就要选择某一个运行时间(也就是代码运行到哪一行),如下图:

Center

i. 上图中,

  1. 第一个栈A是主线程main()方法运行带System.out.pringln(“Hello Java”);时的运行栈信息,main()方法位于栈A的栈顶;

  2. 第二个栈A是主线程main()方法运行到new JavaThreadDemo().threadMethod();方法时的栈信息,threadMethod()方法位于栈A的栈顶。

  3. 在threadMethod()方法中,运行到start()方法时,会新建立一个线程,新建立的线程也将拥有自己的线程栈B,run()方法位于栈B的栈顶。

  4. 此时,线程栈A和线程栈B并行运行

  5. 由此可以看出,方法调用和线程启动的区别:

a) 方法调用只是在原来的线程栈中调用方法即可。

b) 而线程启动会新建立一个独立的线程栈来运行自己的线程。

b) 线程的生命周期

线程的生命周期包括5中状态:新建、可运行状态、运行状态、阻塞、死亡。

Center 1

i. 新建:创建了一个新的线程对象,但是还没有调用线程的start()方法,此时此案成处于新建状态,如:Thread t1 = new MyThread(“张三”) ;

ii. 可运行状态:调用线程的start()方法,线程进入可运行状态,此时线程等待JVM的调度程序将其变为运行状态

iii. 运行状态:线程调度程序,从众多的可运行状态线程中,选择一个线程来执行。这也是线程进入运行状态的唯一方式,必须有JVM来调度。

iv. 阻塞状态:线程的等待、睡眠和阻塞统称为阻塞状态,此时线程依然是活着的,处于待命状态,知道某个条件出现时,变为可运行状态。

v. 死亡状态:当线程的run()方法执行完毕后,线程结束。此时线程已经不存在,它所占用的所有资源都会被回收。

二、线程阻塞:

a) 线程阻塞有多种,常见的有三种(IO阻塞不讨论):

  1. i. 睡眠:调用线程的sleep()方法进入睡眠状态。

当线程睡眠时,它入睡在某个地方,在苏醒之前不会返回到可运行状态。当睡眠时间到期,则返回到可运行状态。

  1. 线程处于睡眠状态时,JVM调度程序会暂停此线程的执行,从而去执行其他的处于可运行状态的线程。

  2. sleep()方法是Thread的静态方法,只能控制当前线程的睡眠。

  3. 线程睡眠时间到了之后,返回到可运行状态,等待JVM调度。

    1. ii. 等待:

    iii. 获取线程锁而阻塞

b) 让线程暂时离开运行状态的三中方法:

  1. i. 调用线程的sleep()方法,使线程睡眠一段时间
  2. ii. 调用线程的yield()方法,使线程暂时回到可运行状态,来使其他线程有机会执行。
  3. iii. 调用线程的join()方法,使当前线程停止执行,知道当前线程中加入的线程执行完毕后,当前线程才可以执行

三、线程的优先级和让步

a) 线程让步:通过Thread.yield()来实现的,yield()方法的作用是:暂停当前正在执行的线程对象,并执行其他线程。

b) JVM线程调度程序是基于优先级的抢先调度机制。

c) 当线程池中线程都具有相同的优先级,调度程序的JVM自由选择他喜欢的线程;如果存在不同级别的优先级,JVM会有高概率选择级别高的线程,但并不一定选择高的,只是概率大一点而已。

d) 如果是线程池中具有相同的优先级,这个时候调度程序的操作有两种可能:

  1. i. 选择一个线程运行,知道他阻塞或者运行完成为止;
  2. ii. 时间分开,为池内的每个线程提供均匀的运行机会

e) 可以通过setPriority(int newPriority),更改线程的优先级。如:

Thread t = new MyThread();
t.setPriority(8);
t.start();

四、小结:

a) 到目前为止,我们知道了,线程离开运行状态共有3中方法:

  1. i. 调用Thread.sleep():是当前线程睡眠n毫秒以后,进入可执行状态,等待调度;
  2. ii. 调用Thread.yield(): 让当前运行线程回到可运行状态,是的具有相同优先级的线程有机会执行;
  3. iii. 调用join()方法:保证当前线程停止运行,直到该线程所加入的线程完成为止,然而,如果它加入的线程没有存活,则当前线程不需要停止。

b) 除了以上三种方式外,还有下面几种特殊情况可能是线程离开运行状态

  1. i. 线程的run()方法完成;
  2. ii. 在对象上调用wait()方法(不是在线程上);
  3. iii. 线程不能再对象上获得锁定,他正试图运行该对象的方法代码;
  4. iv. 线程调度程序可以决定将当前运行状态移动到可运行状态,以便让另一个线程获得运行机会,而不需要任何理由。

参考文章:http://www.cnblogs.com/riskyer/p/3263032.html

http://www.2cto.com/kf/201409/335651.html

http://www.ruanyifeng.com/blog/2013/04/processes\_and\_threads.html

发表评论

表情:
评论列表 (有 0 条评论,307人围观)

还没有评论,来说两句吧...

相关阅读

    相关 java 线详解

    关于线程的概念 1、程序一般是指一段静态代码,静态对象;进程是程序的一次执行过程或正在运行的程序动态的的过程,有它的产生、存在和消亡的过程;线程是指一个程序内部的一条执行

    相关 java线详解()

    一、概念 1、进程:是指一个内存中运行的应用程序。 每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程。 比如,在windows系统中,一个运行的exe就是一

    相关 线创建详解

    1. 线程的概述 进程:正在运行的程序,负责了这个程序的内存空间分配,代表了内存中的执行区域。 线程:就是在一个进程中负责一个执行路径。 多线程:就是在一个进程中多个执