再谈java线程
线程状态
描述
当线程被创建并启动之后,它既不是已启动就进入到了执行状态,也不是一直处于执行状态。在线程的声明周期中有六中状态。
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接口;用来记录线程记录任务执行完毕后产生的结果。线程的创建于使用。
使用线程池中线程对象的步骤
创建线程池对象。
(使用线程池的工厂类Executors里面提供的静态方法newFixedThreadPool生产一个指定的数量的线程池)
创建Runnable接口子类对象。(task)
(定义一个类,实现Runnable接口,重写run方法设置线程任务,new实现类对象)
提交Runnable接口子类对象。(take task)
(调用ExecutorService中的方法submit,传递线程任务(实现类对象),开启新线程,执行run方法)
关闭线程池。(一般不做)
(调用ExecutorService类中方法shutdown销毁线程池)
(如果线程池关闭就不能再次获取否则报异常)
注意;submit方法结束后,程序并不会终止,是因为线程池控制了线程的关闭将使用完的线程又归还到了线程池中。
再谈java线程的更多相关文章
- 浅谈Java线程安全
浅谈Java线程安全 - - 2019-04-25 17:37:28 线程安全 Java中的线程安全 按照线程安全的安全程序由强至弱来排序,我们可以将Java语言中各种操作共享的数据分为以下五类 ...
- 沉淀再出发:再谈java的多线程机制
沉淀再出发:再谈java的多线程机制 一.前言 自从我们学习了操作系统之后,对于其中的线程和进程就有了非常深刻的理解,但是,我们可能在C,C++语言之中尝试过这些机制,并且做过相应的实验,但是对于ja ...
- 再谈Java数据结构—分析底层实现与应用注意事项
在回顾js数据结构,写<再谈js对象数据结构底层实现原理-object array map set>系列的时候,在来整理下java的数据结构. java把内存分两种:一种是栈内存,另一种是 ...
- JVM系列之:再谈java中的safepoint
目录 safepoint是什么 safepoint的例子 线程什么时候会进入safepoint safepoint是怎么工作的 总结 safepoint是什么 java程序里面有很多很多的java线程 ...
- 浅谈 Java线程状态转换及控制
线程的状态(系统层面) 一个线程被创建后就进入了线程的生命周期.在线程的生命周期中,共包括新建(New).就绪(Runnable).运行(Running).阻塞(Blocked)和死亡(Dead)这五 ...
- 记一次synchronized锁字符串引发的坑兼再谈Java字符串
问题描述 业务有一个需求,我把问题描述一下: 通过代理IP访问国外某网站N,每个IP对应一个固定的网站N的COOKIE,COOKIE有失效时间.并发下,取IP是有一定策略的,取到IP之后拿IP对应的C ...
- 记一次 synchronized 锁字符串引发的坑兼再谈 Java 字符串
业务有一个需求,我把问题描述一下: 通过代理IP访问国外某网站N,每个IP对应一个固定的网站N的COOKIE,COOKIE有失效时间. 并发下,取IP是有一定策略的,取到IP之后拿IP对应的COOKI ...
- 再谈java两种变量(基本类型和引用类型)(综合各路大神)
基本类型: 基本类型自然不用说了,它的值就是一个数字,一个字符或一个布尔值. int a: a=250: //声明变量a的同时,系统给a分配了数据空间. 引用类型: 是一个对象类型,值是什么呢? ...
- 浅谈java线程池实现
再进入主题之前,我们先了解几个概念,对读源码有所帮助,对于线程池的运行状态,有4个级别,分别是RUNNING,SHUTING,STOP,TIDING,TERMINATED 解释如下: The runS ...
随机推荐
- [WesternCTF2018]shrine(SSTI+过滤)
记一道存在过滤的模板注入的题.直接给源代码 import flask import os app = flask.Flask(__name__) app.config['FLAG'] = os.env ...
- 腾讯开源:Kotlin 高性能特效动画组件!
先看一下效果展示: 1. VAP VAP(Video Animation Player)是企鹅电竞开发,用于播放酷炫动画的实现方案. 相比Webp, Apng动图方案,具有高压缩率(素材更小).硬件解 ...
- 关于java新特性lambda表达式的理解即使用
Lambda 表达式的使用 1.举例: (o1,o2) -> Integer.compare(o1,o2); 2.格式: -> : lambda操作符 或 箭头操作符 ->左边 : ...
- 我写一篇文章就是要批评CSDN! 因为蓝湖3.0的更新
对于开发者,经常会使用,学习到各种环境语言和工具 我们不只是在不断的在搬运知识,更多时候我们也是在 分享我们学到的"新知识", 当我们有幸觉得自己发现了新的知识与技术时,作为分享者 ...
- Nginx配置websocket的安全协议wss
//nginx配置wss访问方式 map $http_upgrade $connection_upgrade { default upgrade; '' close; } upstream webso ...
- 中文屋 Chinese room
中文屋 Chinese room 深夜了,假装有个bgm,虽然我真的有个bgm<中间人> 强烈安利,无敌好听,冰老师yyds 开始瞎侃 在经历了机器学习的洗礼以后,感觉人都升华了,本来对于 ...
- Redis配置及攻击利用
Redis配置及攻击利用 Redis及其安全配置 Redis介绍 redis默认会绑定在 0.0.0.0:6379,如果没有进行采用相关的策略,比如添加防火墙规则避免其他非信任来源 ip 访问等,这样 ...
- SpringBoot启动异常 Process finished with exit code 1
记录一下一个报错 : < Springboot项目启动之后直接 Process finished with exit code 1 1. 是否有spring-boot-starter-web依赖 ...
- 题解 b
传送门 考场上只会暴力 \(n^4\) DP,部分分还写炸了 但其实这个DP可以前缀和优化到 \(n^3\) ,我觉得没有这档部分分就没写 但其实是有这一档的,我没有看出来-- 正解想不到 如果我们已 ...
- 题解 Defence
传送门 发现最少次数只和最左,最右及中间最长的全0段有关 本来想启发式合并,结果发现直接线段树合并搭配一个类似山海经的方法就可以过了 yysy,线段树单次合并的具体复杂度并不是 \(O(logn)\) ...