前言

线程作为现代操作系统调度的最小单元,多个线程能够同时执行,这将显著提高程序的性能,而且在当前多核CPU的环境下也能更好的利用资源。Java提供了对多线程的良好支持。线程是多线程的基础。

使用多线程的原因:1. 计算机的核心越来越多,更好的利用硬件资源。2. 更快的响应时间,对于复杂的业务逻辑能够多路进行,当然如果你只是打印一句"Hello World"确实"不需要多线程" 3. Java 已经为多线程编程提供了良好 的编程模型。开发人员可以直接使用,不必重复造轮子。

进程和线程

现代操作系统在允许一个程序时,会为其创建一个进程。而操作系统最小的调度单元是线程,一个进程中可以创建多个线程。

这些线程拥有各自的计数器,堆栈和局部变量。这些线程能够访问进程中共享的内存变量。

Daemon(守护线程) 线程是一种支持型的线程,它主要被作用于程序中后台调度以及支持性工作。用个比较通俗的比喻,任何一个守护线程都是整个JVM中所有非守护线程的保姆。守护线程最典型的应用就是 GC (垃圾回收器)

只要当前JVM实例中尚存在任何一个非守护线程没有结束,守护线程就全部工作;只有当最后一个非守护线程结束时,守护线程随着JVM一同结束工作。

创建线程的方式

继承Thread 实现Runable

  • 继承Thread 重写run()方法
  • 实现Runnable接口重写run()方法

阿里巴巴Java 开发规范中强制规定 线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。如果不使用线程池,有可能造成系统创建大量同类线程而导致消耗完内存或者“过度切换”(CPU上下文切换)的问题。

线程 线程的状态

  • NEW 创建未运行中
  • RUNNING 调用start() 方法后运行中的状态
  • WAITING 等待状态,需notify() 方法通知后返回运行中状态
  • TIME WAITING 超时等待,在给定时间后返回运行中状态
  • BLOCKED 为获取到锁,进入到阻塞状态,在阻塞获取到锁后返回运行中状态
  • TERMINATED 终止状态

线程的状态转换

启动停止线程

  • start() 方法用于启动线程,run()方法是执行体,线程start()启动后会执行run() 方法体内的程序。

停止线程

  • 中断

    • 它表示一个运行中的线程是否被其他线程进行中断操作(被其他线程停止)
    • 其他线程通过调用该线程的 interrupt() 方法对其进行中断操作
    • 线程通过isInterrupted()方法(返回中断标识符)来进行判断是否被中断,
  • 安全的终止线程
    • 类似于中断,通过一个变量的控制来停止线程
      private static class Runner implements Runnable {
      
          private volatile boolean on = true;
      
          @Override
      public void run() {
      while (on && !Thread.currentThread().isInterrupted()) {
      // do something
      }
      } public void stopRunner() {
      on = false;
      }
      }

sleep() 函数线程会让出CPU,给其他需要CPU资源的线程使用

线程和线程之间的通信

线程和线程之间是如何通信和进行协作的呢

方式:

  • volatile 和 synchronized 关键字

    • 多个线程在自己内部都有共享变量的拷贝进行使用,修改共享变量,然后其他线程立刻感知到共享变量的修改
  • 等待通知机制

    • 等待通知机制是两个线程通过一个对象来进行交互,以这个对象作为媒介。一个线程A调用这个对象的wait() 方法进行等待状态,另一个线程B调用notifyAll进行通知。线程A接收到通知返回 进行后续操作。而且调用wait() 方法会释放这个对象的锁。
    • Object 类自带的等待/通知方法
      • notify() 通知一个在对象上等待的线程
      • notifyAll() 通知所有等待在该对象上的线程
      • wait() 调用该方法的线程进入WAITING状态,等待他人通知或中断才会返回
      • wait(long) 超时等待,可以选择等待的时间
      • wait(long,int) 超时等待,对于超时时间进行更细粒度的控制
    • 如何传参?通过共享变量
  • 管道输入/输出流

    • 管道输入/输出流用于线程之间的数据传输。包括了以下四种实现:PipedOutputStream、PipedInputStream、PipedReader、PipedWriter 前两种面向字节,后两种面向字符
    • 对于Poped类型的流,必须先进行绑定,也就是调用connect() 方法。
  • join()方法

    • 线程A 和线程thread ,当线程A执行了thread.join()语句。线程A等待thread线程终止后才从thread.join() 返回。
    • join(longmillis) join(long millis,int nanos)
  • ThreadLocal

    • 线程变量,每个线程可以绑定一个ThreadLocal。ThreadLocal是一个以ThreadLocal对象为键,任意对象为值的存储结构。
    • 对于同一个线程。set() 方法来设置一个值,get()方法获取原先设置的值。

分享一道常见面试题三个线程交替打印从1-100

// 使用 synchronized notifyAll() 实现 wait() 实现
public class PrintNums { private Object lock = new Object();
private volatile int curNum = 1;
private volatile String curThread = "1"; class Runner implements Runnable {
@Override
public void run() {
while (curNum < 101) {
synchronized (lock) {
while (!Thread.currentThread().getName().equals(curThread)) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (curThread.equals("3")) {
curThread = "1";
} else {
curThread = String.valueOf(Integer.valueOf(curThread) + 1);
}
if (curNum < 101) {
System.out.println(
"current thread: " + Thread.currentThread().getName()
+ " cur num: " + curNum++);
} lock.notifyAll();
}
}
}
} public static void main(String[] args) {
PrintNums print = new PrintNums();
Thread thread1 = new Thread(print.new Runner(), "1");
Thread thread2 = new Thread(print.new Runner(), "2");
Thread thread3 = new Thread(print.new Runner(), "3"); thread1.start();
thread2.start();
thread3.start(); System.out.println("main terminate");
} }

运行结果:

main terminate
current thread: 1 cur num: 1
current thread: 2 cur num: 2
current thread: 3 cur num: 3
current thread: 1 cur num: 4
current thread: 2 cur num: 5
current thread: 3 cur num: 6

References

  • 《Java并发编程的艺术》

Java多线程之线程的更多相关文章

  1. Java多线程之线程其他类

    Java多线程之线程其他类 实际编码中除了前面讲到的常用的类之外,还有几个其他类也有可能用得到,这里来统一整理一下: 1,Callable接口和Future接口 JDK1.5以后提供了上面这2个接口, ...

  2. Java多线程之线程的通信

    Java多线程之线程的通信 在总结多线程通信前先介绍一个概念:锁池.线程因为未拿到锁标记而发生的阻塞不同于前面五个基本状态中的阻塞,称为锁池.每个对象都有自己的锁池的空间,用于放置等待运行的线程.这些 ...

  3. Java多线程之线程的同步

    Java多线程之线程的同步 实际开发中我们也经常提到说线程安全问题,那么什么是线程安全问题呢? 线程不安全就是说在多线程编程中出现了错误情况,由于系统的线程调度具有一定的随机性,当使用多个线程来访问同 ...

  4. Java多线程之线程的控制

    Java多线程之线程的控制 线程中的7 种非常重要的状态:  初始New.可运行Runnable.运行Running.阻塞Blocked.锁池lock_pool.等待队列wait_pool.结束Dea ...

  5. Java多线程父子线程关系 多线程中篇(六)

    有的时候对于Java多线程,我们会听到“父线程.子线程”的概念. 严格的说,Java中不存在实质上的父子关系 没有方法可以获取一个线程的父线程,也没有方法可以获取一个线程所有的子线程 子线程的消亡与父 ...

  6. 关于Java多线程的线程同步和线程通信的一些小问题(顺便分享几篇高质量的博文)

    Java多线程的线程同步和线程通信的一些小问题(顺便分享几篇质量高的博文) 前言:在学习多线程时,遇到了一些问题,这里我将这些问题都分享出来,同时也分享了几篇其他博客主的博客,并且将我个人的理解也分享 ...

  7. Java多线程02(线程安全、线程同步、等待唤醒机制)

    Java多线程2(线程安全.线程同步.等待唤醒机制.单例设计模式) 1.线程安全 如果有多个线程在同时运行,而这些线程可能会同时运行这段代码.程序每次运行结果和单线程运行的结果是一样的,而且其他的变量 ...

  8. JAVA多线程之线程间的通信方式

    (转发) 收藏 记 周日,北京的天阳光明媚,9月,北京的秋格外肃穆透彻,望望窗外的湛蓝的天,心似透过栏杆,沐浴在这透亮清澈的蓝天里,那朵朵白云如同一朵棉絮,心意畅想....思绪外扬, 鱼和熊掌不可兼得 ...

  9. java多线程与线程间通信

    转自(http://blog.csdn.net/jerrying0203/article/details/45563947) 本文学习并总结java多线程与线程间通信的原理和方法,内容涉及java线程 ...

  10. java多线程之 ---- 线程死锁

    java多线程之线程死锁 产生死锁的主要原因: 由于系统资源不足. 进程执行推进的顺序不合适. 资源分配不当等. 假设系统资源充足.进程的资源请求都可以得到满足,死锁出现的可能性就非常低.否则就会因争 ...

随机推荐

  1. Educational DP Contest E - Knapsack 2 (01背包进阶版)

    题意:有\(n\)个物品,第\(i\)个物品价值\(v_{i}\),体积为\(w_{i}\),你有容量为\(W\)的背包,求能放物品的最大价值. 题解:经典01背包,但是物品的最大体积给到了\(10^ ...

  2. 流程的python PDF高清版

    免费下载链接:https://pan.baidu.com/s/1qcPjLlFXhVXosIGBKHVVXQ 提取码:qfiz

  3. 在kubernetes集群里集成Apollo配置中心(4)之dubbo服务提供者连接apollo实战

    1.登录portal.od.com(Apollo-portal),新建一个dubbo-demo-service项目 2.在Apollo项目中的dubbo-demo-service添加配置 (1)添加d ...

  4. OpenStack Train版-12.创建虚拟网络并启动实例(控制节点)

    使用VMware虚拟机创建网络可能会有不可预测到的故障,可以通过dashboard界面,管理员创建admin用户的网络环境 1.第一种: 建立公共提供商网络在admin管理员用户下创建 source ...

  5. Pangolin 安装测试 Installation & Examination (Ubuntu 20.04)

    Pangolin 安装测试 Installation & Examination (Ubuntu 20.04) 如题所述,这是一个比较轻松的 Pangolin 安装配置方法,同样是基于 WSL ...

  6. 【情人节选帽子】TCS34725颜色传感器和Python图形界面编程(STM32 HAL库)

    截图 描述: l  STM32 HAL库编程 l  使用模拟IIC通信,方便程序移植 l  Python界面编写,蘑菇头的帽子是什么颜色 l  STM32 HAL库串口通信 l  Python界面使用 ...

  7. 可迭代对象&迭代器&生成器

    在python中,可迭代对象&迭代器&生成器的关系如下图: 即:生成器是一种特殊的迭代器,迭代器是一种特殊的可迭代对象. 可迭代对象 如上图,这里x是一个列表(可迭代对象),其实正如第 ...

  8. memcached php

    What is Memcached? Free & open source, high-performance, distributed memory object caching syste ...

  9. 一个模块如何同时支持 ESM 和 CJS

    一个模块如何同时支持 ESM 和 CJS 模块转化 webpack + babel refs xgqfrms 2012-2020 www.cnblogs.com 发布文章使用:只允许注册用户才可以访问 ...

  10. post upload file & application/x-www-form-urlencoded & multipart/form-data

    post upload file application/x-www-form-urlencoded & multipart/form-data https://stackoverflow.c ...