线程状态

  • 描述

    	当线程被创建并启动之后,它既不是已启动就进入到了执行状态,也不是一直处于执行状态。在线程的声明周期中有六中状态。
    java api中java.lang.Thread.State这个枚举给出了线程的六种状态
    线程状态。 线程可以处于以下状态之一:
    线程状态 导致状态发生条件
    NEW(新建) 线程刚被创建,但是还没有启动,还没有调用start方法
    RUNNABLE(可运行) 线程可以在java虚拟机中运行的状态,可以是正在运行自己的代码,也可能没有,这取决于操作系统处理器
    BLOCKED(锁阻塞) 当一个线程试图获取一个对象锁,而该对象被其他线程所持有,则该线程进入到blocked状态;当该线程持有锁时,该线程就进入到runnable状态
    WAITING(无限等待) 一个线程在等待另一个线程执行一个动作(新建),该线程就进入到waiting状态,进入这种waiting状态后是不能自动唤醒的,必须等待另一个线程调用notify或者notifyAll方法才能唤醒
    TIMED_WAITING(计时等待) 同waiting状态,有几个方法有超时参数,调用他们将进入timed waiting状态,这一状态一直保持到超时期满或者是收到了唤醒通知。带有超时参数的常用方法有Thread.sleep(),Object.wait().
    TERMINATED(被终止) 因为run方法正常退出而死亡,或者因为没有捕获的异常终止run方法而死亡。

    TIMED_WAITING(计时等待)

    TIMED_WAITING在java api中描述为;一个正在限时等待另一个线程执行一个(唤醒)动作的线程处于这一状态,其实当我们调用sleep方法之后,当前正在执行的线程就进入到了计时等待状态。
    
    //1.进入到thread waiting状态的是一种常见的操作是调用sleep方法,单独的线程也可以调用,不一定非要有协作关系
    //2.为了让其他线程有机会执行到,一般建议将Thread.sleep()调用放到run方法内,这样才能保证线程执行过程中会睡眠
    //sleep与锁无关,线程睡眠到期会自动苏醒,并返回到runnable状态。sleep里面的参数指定的时间是线程不会不会运行的最短时间,因此,sleep方法不能保证该线程睡眠到期后就会立刻执行

    BLOCKED(锁阻塞)

    BLOCKED状态在java api中描述为;一个正在阻塞等待一个监视器锁(锁对象)的线程处于这一状态。
    比如;线程a与线程b代码中同时使用一把锁,如果线程a获取到锁对象,线程a就进入runnable状态,反之线程b就进入到blacked状态。

    WAITING(无限等待)

    waiting状态在java api中的描述为;一个正在无线等待另一个线程执行一个特别的(唤醒)动作的线程处于这一状态。
    一个调用了某个对象 锁.wait()方法的线程,会等待另一个线程调用此对象的 锁.notify()或者锁.notifyAll()方法
    其实waiting状态它并不是一个线程的操作,它体现的是多个线程之间的'通信',可以理解为多个线程之间的协作关系,多个线程争取锁,同时相互之间又存在协作关系

等待唤醒机制

  • 线程间通信

    • 概念

      多个线程在处理同一个资源,但是处理的动作(线程的任务)却又不同。
    • 为什么要处理线程之间的通信;

      多个线程并发在执行时,在默认情况下cpu是随机切换线程的,当我们需要多个线程共同来完成一件任务时,并且我们希望他们有规律的执行,那么多线程之间就需要一些协调通信,以此来帮助我们达到多线程共同操作一份数据。
    • 如果保证线程之间通信有效利利用资源;

      多个线程在处理同一资源的时候,并且任务还不相同,需要线程通信来帮助我们解决线程之间对同一个变量的使用或者操作。
      就是多个线程在操作同一份数据时,避免同一个变量的争夺,也就是我们需要通过一定的手段使各个线程有效的利用资源。这种手段就是---》等待唤醒机制
    • 什么是等待唤醒机制?

      这是多个线程间的一种协作机制。
      就是一个线程进行规定协作后,就进入到了等待状态'wait()',等待其他线程执行完他们的指定代码后,再将其唤醒'notify()';
      在有多个线程进行等待时,如果需要,可以使用'notifyAll()'来唤醒所有的等待线程。
      wait/notify就是线程间的一种协作机制。 等待唤醒中的方法;
      等待唤醒机制就是用来解决线程间通信问题的。可以使用到的方法有三个如下
      1.wait();线程不在活动,不在参与调度,进入到waiting设置中,因此不会浪费cpu资源,也不会去竞争锁了,这时的线程状态就是waiting,他还要等着别的线程执行一个特别的动作,就是唤醒通知'notify()',在这个对象上等待的线程从wait set中释放出来,重新进入到调度队列(ready queue)中。
      2.notify();选取通知对象的wait set中的一个线程释放。
      3.notifyAll();释放所通知对象的wait set中的全部线程。 //备注;哪怕只同时了一个等待线程,被通知的线程也不能立即回复执行,因为它当初中断的地方是在同步块内,而此刻它已经不持有锁了,所以它需要再次尝试着去获取锁(很可能面临其他线程的竞争),成功后才能当初调用wait方法之后的地方恢复执行。 //总结;如果能获取到锁,线程就从waiting状态转变成runnable状态,否则,从wait set中,又进入set中,线程就从waiting状态转变成blocked状态。 '调用wait和notify方法的注意细节:'
      1.wait方法和notify方法必须有同一个锁对象调用。因为,对应的锁对象可以通过notify唤醒使用同一个锁对象的wait方法后的线程。
      2.wait与notify方法是属于Object类中的方法。因为锁对象可以是任意对象,而任意对象的所属类都是继承了Object类的。
      3.wait与notify方法必须在同步代码块中或者同步方法中使用。因为必须通过锁对象调用这两个方法来实现等待与唤醒。
      包子铺线程生产包子,吃货线程消费包子,当包子没的时候状态为false,吃货线程需要等待,包子铺线程生产包子包子状态为true,通知吃货线程并解除吃货状态,因为已经有包子,,包子铺线程进入等待状态,接下来,吃货线程能够进一步取决于锁的获取状态情况,如果吃货线程取得到了锁,就执行吃包子动作,包子吃完了包子状态为false,通知包子铺线程解除包子铺线程等待状态,此时吃货线程就进入到等待状态,包子铺线程能否进一步执行则取决于锁的获取情况。

线程池

  • 概念

    	一个容纳多个线程的容器,其中的线程可以反复的使用,省去了频繁的创建线程对象的操作,无需反复创建线程而消耗过多的资源。
    
        由于线程池中有很多操作都是与优化系统资源有关的,
  • 线程池的工作原理

  • 线程的好处

    1.降低了资源消耗,减少了线程的创建于销毁的次数,每个工作线程都可以被重复利用,可执行多个任务
    2.提高了响应速度。当任务到达时,任务可以不需要等到线程的创建就能立即执行。
    3.提高了线程的客观理性,可以根据系统的承受能力,调整线程中工作线程的数目,防止因为消耗过多的内存,而导致服务器的崩溃 (每个线程需要大约1mb,线程开的越多,消耗的内存也就越大,死机的风险也就更高)。
  • 线程池的使用(JDK 5.0)

    • 描述

      java.util.concurrent.Executor ,但是严格意义讲,Executor它并不是一个线程池,他只是执行线程的一个工具,真正的线程接口时 java.util.concurrent.ExecutorSerivice(线程接口) 。
      
      在java.util.concurrent.Excutors 线程工程类提供了一些静态工厂,生产一些常用的线程池,官方建议使用Executors来创建线程池对象。
      
      void execute(Runnable command) :执行任务/命令,没有返回值,一般用来执行Runnable
      <T> Future<T> submit(Callable<T> task):执行任务,有返回值,一般又来执行Callable
      void shutdown() :关闭连接池
    • Executors 创建线程的常用方法

      static ExecutorService newFixedThreadPool(int nThreads);返回的就是线程池对象(创建的是有界的线程池,也就是池中的线程个数可以指定最大数量)
      Future<?> submit(Runnable task); 获取线程池中的某一个线程对象,并执行。
      Future接口;用来记录线程记录任务执行完毕后产生的结果。线程的创建于使用。
    • 使用线程池中线程对象的步骤

      1. 创建线程池对象。

        (使用线程池的工厂类Executors里面提供的静态方法newFixedThreadPool生产一个指定的数量的线程池)

      2. 创建Runnable接口子类对象。(task)

        (定义一个类,实现Runnable接口,重写run方法设置线程任务,new实现类对象)

      3. 提交Runnable接口子类对象。(take task)

        (调用ExecutorService中的方法submit,传递线程任务(实现类对象),开启新线程,执行run方法)

      4. 关闭线程池。(一般不做)

        (调用ExecutorService类中方法shutdown销毁线程池)

        (如果线程池关闭就不能再次获取否则报异常)

      注意;submit方法结束后,程序并不会终止,是因为线程池控制了线程的关闭将使用完的线程又归还到了线程池中。


再谈java线程的更多相关文章

  1. 浅谈Java线程安全

    浅谈Java线程安全 - - 2019-04-25    17:37:28 线程安全 Java中的线程安全 按照线程安全的安全程序由强至弱来排序,我们可以将Java语言中各种操作共享的数据分为以下五类 ...

  2. 沉淀再出发:再谈java的多线程机制

    沉淀再出发:再谈java的多线程机制 一.前言 自从我们学习了操作系统之后,对于其中的线程和进程就有了非常深刻的理解,但是,我们可能在C,C++语言之中尝试过这些机制,并且做过相应的实验,但是对于ja ...

  3. 再谈Java数据结构—分析底层实现与应用注意事项

    在回顾js数据结构,写<再谈js对象数据结构底层实现原理-object array map set>系列的时候,在来整理下java的数据结构. java把内存分两种:一种是栈内存,另一种是 ...

  4. JVM系列之:再谈java中的safepoint

    目录 safepoint是什么 safepoint的例子 线程什么时候会进入safepoint safepoint是怎么工作的 总结 safepoint是什么 java程序里面有很多很多的java线程 ...

  5. 浅谈 Java线程状态转换及控制

    线程的状态(系统层面) 一个线程被创建后就进入了线程的生命周期.在线程的生命周期中,共包括新建(New).就绪(Runnable).运行(Running).阻塞(Blocked)和死亡(Dead)这五 ...

  6. 记一次synchronized锁字符串引发的坑兼再谈Java字符串

    问题描述 业务有一个需求,我把问题描述一下: 通过代理IP访问国外某网站N,每个IP对应一个固定的网站N的COOKIE,COOKIE有失效时间.并发下,取IP是有一定策略的,取到IP之后拿IP对应的C ...

  7. 记一次 synchronized 锁字符串引发的坑兼再谈 Java 字符串

    业务有一个需求,我把问题描述一下: 通过代理IP访问国外某网站N,每个IP对应一个固定的网站N的COOKIE,COOKIE有失效时间. 并发下,取IP是有一定策略的,取到IP之后拿IP对应的COOKI ...

  8. 再谈java两种变量(基本类型和引用类型)(综合各路大神)

    基本类型: 基本类型自然不用说了,它的值就是一个数字,一个字符或一个布尔值. int  a:   a=250: //声明变量a的同时,系统给a分配了数据空间. 引用类型: 是一个对象类型,值是什么呢? ...

  9. 浅谈java线程池实现

    再进入主题之前,我们先了解几个概念,对读源码有所帮助,对于线程池的运行状态,有4个级别,分别是RUNNING,SHUTING,STOP,TIDING,TERMINATED 解释如下: The runS ...

随机推荐

  1. Java面向对象07——封装

    封装 (补充 this关键字):  package oop.demon01.demon03; ​ /*    封装的意义:        1. 提高程序的安全性,保护代码        2. 隐藏代码 ...

  2. 『Java』String类使用方法

    Java中的字符串 java.lang.String类表示字符串类,Java程序中所有字符串文字都可以看作实现该类的实例. 特点: 字符串不可变:字符串的值在创建后不能在发生改变 public cla ...

  3. JVM G1GC的算法与实现

    G1GC 是什么? 一些基本概念 实时性 G1GC 有什么特点? G1GC 的堆结构是什么样的? G1GC 的执行过程是什么样的? 并发标记 并发标记是什么 标记位图 执行步骤 步骤 1--初始标记阶 ...

  4. 从零开始实现简单 RPC 框架 3:配置总线 URL

    URL 的定义 URL 对于大部分程序猿来说都是很熟悉的,其全称是 Uniform Resource Locator (统一资源定位器).它是互联网的统一资源定位标志,也就是指网络地址. 一个标准的 ...

  5. 【网络编程】TCPIP-7-域名与网络地址

    目录 前言 7. 域名与网络地址 7.1 IP 7.2 域名 7.3 DNS 7.4 IP地址与域名之间的转换 7.4.1 利用域名获取IP地址 7.4.2 利用IP地址获取域名 7.4.3 升级版的 ...

  6. 题解 u

    传送门 这里AC解法因为手残 tag2[min(r+l, n+1)][min(c+l+1, n+1)]+=s; 写成 tag2[min(r+l, n+1)][c+l+1]+=s; 惨遭RE,以后注意查 ...

  7. Java社区——个人项目开发笔记(一)

    1.maven安装与测试 安装过程略,常用的maven命令行工具: mvn --version 查看maven版本 mvn compile 编译maven工程 mvn clean 删除编译文件 mvn ...

  8. WPF 中的style 样式

    WPF相较于以前学的WinForm,WPF在UI设计与动画方面的炫丽是最吸引我来学习的.在WPF中XMAL代码的引入使得代码的编写能够前后端分离,为获得更好的界面,也使得我们不得不分出一半的时间花在前 ...

  9. 【linux】less 命令详解

    转自:https://www.cnblogs.com/GNblog/p/6932252.html less 工具也是对文件或其它输出进行分页显示的工具,应该说是linux正统查看文件内容的工具,功能极 ...

  10. dubbo暴露原理及引用过程

    服务暴露 服务引用: