文章目录

  • 线程
    • 1 进程和线程的区别
    • 2 线程的创建方式
      • 2.1 继承Thread类并重写run方法
      • 2.2 实现Runnable接口
      • 2.3 实现Callable接口
      • 2.4 线程池
      • 2.5 小结
    • 3 线程的通知和等待
      • 3.1 wait()函数
      • 3.2 wait(long timeout)函数
      • 3.3 notify()函数
      • 3.4 notifyAll()函数
      • 3.5 sleep()函数
      • 3.6 yield()函数
      • 3.7 join()函数
    • 4 线程的中断
      • 4.1 void interrupt()
      • 4.2 boolean isInterrupted()
      • 4.3 boolean interrupted()
    • 5 线程状态
    • 6 上下文切换
    • 7 线程的优先级
    • 8 线程组
    • 9 守护线程与用户线程

线程

1 进程和线程的区别

进程时操作系统进行资源分配的基本单位,线程是CPU调度的基本单位

一个进程中有多个线程,多个线程共享方法区,但是每个线程有自己的程序计数器

程序计数器:用来记录线程当前要执行的指令地址,用于上下文切换时可以继续从之前的位置执行。如果执行的是native方法,则程序计数器为undefined

栈:用于存储该线程的局部变量

堆:进程中最大的一块内存,被所有线程共享,主要存放new操作创建的对象实例

方法区:用来存在JVM加载的类、常量以及静态变量等信息

在Java中,启动main函数就启动了一个JVM进程,而main函数所在的线程就是主线程

2 线程的创建方式

当创建完Thread对象后,该线程并没有被启动执行,直到调用start方法后才执行

调用start方法后,线程处于就绪状态,待获取CPU时间片后才真正开始运行

调用start()方法方可启动线程并使线程进入就绪状态,直接执行 run()方法的话不会以多线程的方式执行

2.1 继承Thread类并重写run方法

public static class MyThread extends Thread {private String name;public MyThread() {}public MyThread(String name) {this.name = name;}@Overridepublic void run() {System.out.println(name);}
}public static void main(String[] args) {Thread MyThread1 = new MyThread("name1");MyThread1.start();
}

2.2 实现Runnable接口

public static class MyRunnable implements Runnable {private String name;public MyRunnable() {}public MyRunnable(String name) {this.name = name;}@Overridepublic void run() {System.out.println(name);}
}public static void main(String[] args) {Runnable MyRunnable1 = new MyRunnable("hahah1");new Thread(MyRunnable1).start();
}

2.3 实现Callable接口

public static class MyCallable implements Callable<String> {@Overridepublic String call() throws Exception {return "123";}
}public static void main(String[] args) {FutureTask<String> futureTask = new FutureTask<>(new MyCallable());new Thread(futureTask).start();try {String res = futureTask.get();System.out.println(res);} catch (Exception e) {e.printStackTrace();}
}

2.4 线程池

2.5 小结

继承Thread的优势:在run方法内获取当前线程直接使用this

继承Thread的劣势:Java不支持多继承,继承Thread类就不能再继承其他的类。任务与代码没有分离,当多个线程执行一样的任务时需要多份任务代码?

实现Runnable的优势:可以多继承

实现Callable的优势:可以有返回值

3 线程的通知和等待

3.1 wait()函数

当线程调用了共享变量的wait()方法时,该线程阻塞,直到其他线程调用notify()或notifyAll(),或调用interrupt()中断

调用wait()函数,需要事先获取该共享变量的锁,否则会抛出IllegalMonitorStateException异常

执行wait()函数后,会释放已经获得的资源

虚假唤醒:一个线程可以从挂起状态转变为可运行状态,即使该线程没有被其他线程调用notify()或中断。为防止虚假唤醒,可以通过while循环不断判断是否满足唤醒条件,如果不满足则一直调用wait()

3.2 wait(long timeout)函数

线程在挂起后,超过timeout ms的时间,会自动返回

3.3 notify()函数

一个线程调用共享变量的notify()方法,会随机唤醒在该共享变量上调用过wait()方法挂起的一个线程

调用notify()函数,同样需要事先获取共享变量的锁,否则会抛出IllegalMonitorStateException异常

被唤醒的线程不一定会继续运行,因为该线程可能还需要获得共享变量的锁才能继续运行

3.4 notifyAll()函数

会唤醒在该共享变量上调用过wait()方法挂起的所有线程

3.5 sleep()函数

Thread类的静态方法,用于让线程睡眠,让出CPU时间片,不参与CPU调度,指定时间后返回处于就绪状态

但是该函数不会释放已经获得的资源

3.6 yield()函数

Thread类的静态方法,用于让线程交出CPU使用权,线程处于就绪状态,CPU重新调度线程的时候依旧有可能会调度到这个线程

该函数同样不会释放已经获得的资源

3.7 join()函数

该方法是Thread类提供的无参无返回值的方法

调用join()的线程,会阻塞,直到被调用join()方法的线程执行完毕后,该线程才会继续执行

用于多个线程加载资源,等待多个线程全部加载完毕再汇总处理

4 线程的中断

中断是一种线程间的协作模式,通过设置中断标志并不能直接中断线程,而是由被中断的线程自行决定

在wait()方法、sleep()、join()方法调用后,别的线程调用了该线程的interrupt(),则会抛出InterruptedException异常

4.1 void interrupt()

为某个线程设置中断标志位

4.2 boolean isInterrupted()

检测被调用线程是否被中断,是则返回true,否则返回false

4.3 boolean interrupted()

检测当前线程是否被中断,是则返回true,否则返回false,与上述不同的是,该方法会清除中断标志位

该方法是Thread类的静态方法,所以不管被调用的是哪个线程,获取的都是当前调用这个函数的线程是否中断

5 线程状态

  • new:初始状态。线程创建了,但是还未调用start方法启动线程

  • runnable:运行状态。包含操作系统中的就绪状态和运行状态,可能在运行,也可能在等待CPU调度

  • blocked:阻塞状态。线程正在等待锁的释放,进入同步块

  • waiting:等待状态。线程处于等待状态,等待其他线程唤醒。Object.wait()、Thread.join()、LockSupport.park()会使得线程进入等待状态

  • timed_waiting:超时等待状态。超过指定时间则自动唤醒

  • terminated:终止状态。线程执行完毕

线程状态转换图

6 上下文切换

线程在时间片内占用CPU执行任务,当时间片用尽则处于就绪状态让出CPU,从当前线程的上下文切换到了其他线程

切换线程上下文时需要保存当前线程执行的现场,再次执行到该线程时恢复现场

7 线程的优先级

Java中线程优先级范围是1-10,默认优先级为5。优先级只是给系统一个参考值,线程最终在操作系统的优先级还是由操作系统决定

thread1.setPriority(10)

8 线程组

Java中用ThreadGroup来表示线程组,如果创建线程时没有明确指定,则使用父线程的线程组作为自己的线程组

线程组统一异常处理

public class ThreadGroupDemo {public static void main(String[] args) {ThreadGroup threadGroup1 = new ThreadGroup("group1") {// 继承ThreadGroup并重新定义以下方法// 在线程成员抛出unchecked exception// 会执行此方法public void uncaughtException(Thread t, Throwable e) {System.out.println(t.getName() + ": " + e.getMessage());}};// 这个线程是threadGroup1的一员Thread thread1 = new Thread(threadGroup1, new Runnable() {public void run() {// 抛出unchecked异常throw new RuntimeException("测试异常");}});thread1.start();}
}

9 守护线程与用户线程

Java中线程分为:daemon线程(守护线程)和user线程(用户线程)

守护线程是否结束,并不影响JVM的退出,当非守护线程都结束时,JVM会退出

thread.setDaemon(true);

main线程运行结束后,JVM会自动创建一个DestroyJavaJVM的线程,等待所有用户线程结束后终止JVM

Java并发(一)——线程相关推荐

  1. Java 并发编程 -- 线程池源码实战

    一.概述 小编在网上看了好多的关于线程池原理.源码分析相关的文章,但是说实话,没有一篇让我觉得读完之后豁然开朗,完完全全的明白线程池,要么写的太简单,只写了一点皮毛,要么就是是晦涩难懂,看完之后几乎都 ...

  2. Java并发编程——线程池的使用

    在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统 ...

  3. Java并发编程—线程间协作方式wait()、notify()、notifyAll()和Condition

    原文作者:Matrix海 子 原文地址:Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition 目录 一.wait().notify()和notifyA ...

  4. java workerdone_【架构】Java并发编程——线程池的使用

    前言 如果我们要使用线程的时候就去创建一个,这样虽然非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为 ...

  5. Java并发教程–线程池

    Java 1.5中提供的最通用的并发增强功能之一是引入了可自定义的线程池. 这些线程池使您可以对诸如线程数,线程重用,调度和线程构造之类的东西进行大量控制. 让我们回顾一下. 首先,线程池. 让我们直 ...

  6. Java并发编程-线程安全基础

    线程安全基础 1.线程安全问题 2.账户取款案例 3.同步代码块synchronized synchronized的理解 java中有三大变量的线程安全问题 在实例方法上使用synchronized ...

  7. 灵魂发问,Java并发和线程池,只言片语真的可以讲清楚吗?

    线程池 最近看到线程池,被里边乱七八槽的参数给搞晕了,你能不能给我讲讲呀? 对于从事后端开发的同学来说,线程是必须要使用了,因为使用它可以提升系统的性能.但是,创建线程和销毁线程都是比较耗时的操作,频 ...

  8. 灵魂发问!Java并发和线程池,只言片语真的可以讲清楚吗?

    线程池 最近看到线程池,被里边乱七八槽的参数给搞晕了,你能不能给我讲讲呀? 对于从事后端开发的同学来说,线程是必须要使用了,因为使用它可以提升系统的性能.但是,创建线程和销毁线程都是比较耗时的操作,频 ...

  9. Java并发编程—线程同步类

    原文作者:洲洋1984 原文地址:Java 并发包中的高级同步工具 Java 中的并发包指的是 java.util.concurrent(简称 JUC)包和其子包下的类和接口,它为 Java 的并发提 ...

  10. Java 并发总结——线程池

    一.线程池 在程序启动的时候就创建若干线程来响应处理,它们被称为线程池,里面的线程叫工作线程 (1)线程池的作用 1.降低资源消耗.通过重复利用已创建的线程降低线程创建和销毁造成的消耗. 2.提高响应 ...

最新文章

  1. 腾讯告诉你小孩子的钱也有多好赚,一月花费25万不是梦!
  2. Django中六个常用的自定义装饰器
  3. 时频分析:短时傅立叶变换实现(5)
  4. mysql 数据库学习(触发器)
  5. Matrix-tree 定理的一些整理
  6. 欧拉回路 欧拉路径
  7. mysql合集_Mysql数据库知识点合集
  8. composer安装
  9. 摄影测量学之共线方程的应用
  10. Debian 配置Bind9 DNS服务器
  11. ADC前端电压跟随器和ADC相关参数之---分辨率和精度(INL和DNL)
  12. H.265编码原理入门
  13. JetChat-简仿微信聊天应用
  14. matlab图上面加箭头,利用matlab如何在图形中绘制箭头
  15. 论文阅读笔记《Siamese Convolutional Neural Network for Camera Pose Estimation and Visual Servoing》
  16. 如何使文章分栏脚注不分栏?
  17. html5抓鱼游戏,小班捉小鱼游戏教案
  18. 如何让电脑运行速度变快
  19. django-外键和表关系
  20. 【通知】关于SRRC认证无线电发射设备型号核准的通知

热门文章

  1. 2017-06-23
  2. 注册、登陆、审核练习
  3. WPS2012交叉引用技巧,word比wps这点强更新參考文献
  4. Windows 7如何限制运行特定的应用程序(转载)
  5. MVVM模式与Reactive Extensions 学习与思考
  6. PHP网页截图-网页快照实现
  7. 安卓渗透测试工具——Drozer(安装和使用)
  8. 训练集,验证集,测试集比例
  9. 【原创】IDEA一定要改的八条配置
  10. sqlserverdatasouce控件如何让添加删除修改自动化