java学习之- 线程运行状态
标签(空格分隔): 线程运行状态
线程的运行状态:
如下是是我编写的一个图,大家可以作为参考:

1.new一个thread子类也是创建了一个线程;
2.创建完毕之后start()-----运行,
3.然后从运行-------sleep(time)----冻结----sleep(time)时间到了,恢复到运行;
4.还有一种,是线程运行的时候------wait时间------到冻结状态-------然后notify()唤醒-----然后恢复到运行状态;
5.消亡:线程运行中/冻结:stop()/run方法结束---------消亡;
6.临时状态:当前状态等待CPU的执行权,具备运行资格没有执行权,
7.冻结:放弃了执行资格;
8.冻结状态-----恢复---临时状态/运行状态;
获取线程的对象和名称:
创建了对象之后,都要匹配一个名称,线程的名称都要定义在线程的事物里面:
class Demo extends Thread{
private String name;
Demo(String name){
this.name=name;
}
public void run(){//将运行的代码放在run方法中
for(int x=0;x<60;x++) {
System.out.println(this.getName()+"demo run-----"+x);
}
}
}
class ThreadDemo{
public static void main(String[] args){
Demo d1= new Demo("one");//创建好一个线程
Demo d2= new Demo("two");
d1.start();
d2.start();
for(int x=0;x<60;x++){
System.out.println("helloworld!----"+x);
}
}
}
- 原来线程都有自己默认的名称,Thread-编号,该编号从零开始;
2.上述的名称是不是不太好看,这里可以使用set方法来定义名称;
获取当前线程的名称:
- static Thread currentThread():获取当前线程的对象;
getName():获取线程名称;
设置线程名称:setName或者构造方法;
练习:
- 需求是一个简单的卖票程序,多个窗口卖票,1号窗口在卖的时候,2号也在卖;多个窗口同时卖票,
观察如下的程序:
class Ticket extends Thread{
private int tick=100;
public void run(){
while (true){
if(tick>0) {
System.out.println(Thread.currentThread().getName()+"sale:" + tick--);
}
}
}
}
class TickDemo{
public static void main(String[] args){
Ticket t1=new Ticket();
Ticket t2=new Ticket();
Ticket t3=new Ticket();
Ticket t4=new Ticket();
t1.start();
t2.start();
t3.start();
t4.start();
}
}
执行结果:
发现100个票,卖出去了400张票;每个对象里面包含了100张票;
如何实现:100张票4个窗口正常售卖呢?,我们可以通过static定义变量来实现,如下
class Ticket extends Thread{
private static int tick=100;
public void run(){
while (true){
if(tick>0) {
System.out.println(Thread.currentThread().getName()+"sale:" + tick--);
}
}
}
}
class TickDemo{
public static void main(String[] args){
Ticket t1=new Ticket();
Ticket t2=new Ticket();
Ticket t3=new Ticket();
Ticket t4=new Ticket();
t1.start();
t2.start();
t3.start();
t4.start();
}
}
执行通过;
- 但是一般我们不使用静态,因为静态的生命周期比较长;
- 我们使用Thread创建线程不能实现了;
runable接口:
- Runable接口应该由那些打算通过某一线程执行实例的类来实现,类必须顶一个称为run的无参数方法,设计该接口的目的就是提供一个公共协议,例如,Thread类实现了Runable,激活的意思是某个线程已经启动并且尚未停止;
class Ticket implements Runnable{
private static int tick=100;
public void run(){
while (true){
if(tick>0) {
System.out.println(Thread.currentThread().getName()+"sale:" + tick--);
}
}
}
}
class TickDemo{
public static void main(String[] args){
// Ticket t1=new Ticket();
// Ticket t2=new Ticket();
// Ticket t3=new Ticket();
// Ticket t4=new Ticket();
// t1.start();
// t2.start();
// t3.start();
// t4.start();
Ticket t=new Ticket();
Thread t1=new Thread();
Thread t2=new Thread();
Thread t3=new Thread();
Thread t4=new Thread();
t1.start();
t2.start();
t3.start();
t4.start();
}
}
上述代码:能否实现呢?
分析:t1调用运行的run()是Thread里面的run,在这次代码里面未重写;
package com.wangaling;
class Ticket implements Runnable{
private static int tick=100;
public void run(){
while (true){
if(tick>0) {
System.out.println(Thread.currentThread().getName()+"sale:" + tick--);
}
}
}
}
class TickDemo{
public static void main(String[] args){
// Ticket t1=new Ticket();
// Ticket t2=new Ticket();
// Ticket t3=new Ticket();
// Ticket t4=new Ticket();
// t1.start();
// t2.start();
// t3.start();
// t4.start();
Ticket t=new Ticket();
Thread t1=new Thread(t);
Thread t2=new Thread(t);
Thread t3=new Thread(t);
Thread t4=new Thread(t);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
执行结果:
上述代码可以正常实现售票的功能;
创建线程的第二种方式,实现runnable接口
步骤1:
1。定义类实现Runable接口;
2.覆盖Runable接口中的run方法:将线程要运行的代码存在在run方法中
3.通过Thread类建立线程对象
4.将Runable接口的子类对象作为实际参数传递给Thread类的构造函数:为什么要将Runable接口的子类的对象传递给Thread的构造函数,因为,自定义的run方法所属的对象是Runable接口的子类对象,所以要让线程去指定指定对象的run方法,就必须明确该run方法所属的对象;
5.调用Thread类的start方法开启线程,并调用Runable接口子类的run方法;
实现方式和继承方式有很么区别?
- 1.实现方式好处:避免了单继承的局限性,在定义线程的时候建议是用实现方式,可以避免单继承的实现性;
两种方式区别:
- 继承Thread:线程代码存放在Thread子类的run方法中;
实现Runable,线程代码存在接口的子类的run方法
上述程序的分析:
1。通过分析发现:打印票会出现:0,-1,-2等错票;
多线程的运行出现了安全问题:
- 问题的原因:
当多条语句在操作同一个线程共享数据时,一个线程对多条语句执行了一部分还没有执行完另一个线程已经参与进来了,导致了共享数据的错误
解决办法:
对多条操作共享数据的语句,只能让一个线程都执行完毕,在执行过程中,其他线程不可以执行;(就是说拿到了执行权也不让他执行)
- java对多线程提供了专业的解决方式,就是同步代码块,
synchronized(对象){
需要被同步的代码块,怎么判断哪些代码块需要同步,就看谁操作了共享数据;
}
对象如同锁,持有锁的线程可以在同步中执行,没有持有锁的线程即使获得了CPU的执行权限,也进不去,因为没有获取锁;--理解这个概念可以理解火车上的卫生间;- 同步的前提:
1.必须要有2个或者2个以上的线程;
2.必须多个线程使用一个锁;
必须保证同步中只有一个线程运行,有些需要同步,有些不需要同步;
好处:解决多线程的安全问题;
弊端:每个线程在获取到CPU权限之后,每次都要判断一下锁,这样使程序会变得非常的慢;
package com.wangaling;
class Ticket implements Runnable{
private static int tick=100;
Object obj=new Object();
public void run(){
while (true){
synchronized (obj){
if (tick > 0) {
try(Thread.sleep(10);)catch(Exception e){}
System.out.println(Thread.currentThread().getName() + "sale:" + tick--);
}
}
}
}
}
class TickDemo{
public static void main(String[] args){
// Ticket t1=new Ticket();
// Ticket t2=new Ticket();
// Ticket t3=new Ticket();
// Ticket t4=new Ticket();
// t1.start();
// t2.start();
// t3.start();
// t4.start();
Ticket t=new Ticket();
Thread t1=new Thread(t);
Thread t2=new Thread(t);
Thread t3=new Thread(t);
Thread t4=new Thread(t);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
/*
需求:
银行有一个金库,有两个储户分别存300,每次存100,存3次。
目的:改程序是否有安全问题,如果有,如何解决?
如何找问题:
1.明确哪些代码是多线程运行的代码
2.明确共享数据
3.明确多线程运行代码中哪些语句是操作共享数据的。
*/
class Bank{
private int sum;
Object obj=new Object();
public void add(int n ){
synchronized (obj){
sum=sum+n;
try{Thread.sleep(10);}
catch(Exception e){};
System.out.println("sum="+sum);
}
}
}
class Cus implements Runnable{
private Bank b=new Bank();
public void run(){
for(int x=0;x<3;x++){
b.add(100);
}
}
}
class BankDemo{
public static void main(String[] args){
Cus c=new Cus();
Thread t1=new Thread(c);
Thread t2=new Thread(c);
t1.start();
t2.start();
}
如上述的需求我们可以修改为同步函数:
class Bank{
private int sum;
// Object obj=new Object();
public synchronized void add(int n ){
// synchronized (obj){
sum=sum+n;
try{Thread.sleep(10);}
catch(Exception e){};
System.out.println("sum="+sum);
// }
}
}
class Cus implements Runnable{
private Bank b=new Bank();
public void run(){
for(int x=0;x<3;x++){
b.add(100);
}
}
}
class BankDemo{
public static void main(String[] args){
Cus c=new Cus();
Thread t1=new Thread(c);
Thread t2=new Thread(c);
t1.start();
t2.start();
}
- 问题通过上边的学习我们可以对:函数进行同步,那如下同步可以吗?
class Ticket implements Runnable{
private int num=1000;
public synchronized void run(){
while(true) {
if(num>0){
try{
Thread.sleep(10);
}catch (Exception e){}
System.out.println(Thread.currentThread().getName()+"sale"+num--);
}
}
}
}
class ThisLockDemo{
public static void main(String[] args){
Ticket t=new Ticket();
Thread t1= new Thread(t);
Thread t2=new Thread(t);
Thread t3=new Thread(t);
t1.start();
t2.start();
t3.start();
}
}
- 答案不可以,我们可以把run方法体抽离出来单独写一个函数,然后在run里面调用就可以了
class Ticket implements Runnable{
private int num=1000;
public void run(){
while(true){
show();}
}
public synchronized void show(){
if(num>0){
try{
Thread.sleep(10);
}catch (Exception e){}
System.out.println(Thread.currentThread().getName()+"sale"+num--);
}
}
}}
class ThisLockDemo{
public static void main(String[] args){
Ticket t=new Ticket();
Thread t1= new Thread(t);
Thread t2=new Thread(t);
Thread t3=new Thread(t);
t1.start();
t2.start();
t3.start();
}
}
- 上述的例子:同步函数用的哪锁呢?
1.函数需要被对象调用,函数都有一个所属对象的引用,就是this,所以同步函数使用的就是this;
2.通过该程序进行验证,使用两个线程进行卖票,一个线程在同步代码块中,一个在同步函数中,都在执行卖票程序,如果同步不会出现错误的票;
class Ticket implements Runnable{
private int num=1000;
Object obj =new Object();
boolean flag =true;
public void run(){
if (flag){
while(true){
synchronized(this){
if(num>0){
try{
Thread.sleep(10);
}catch (Exception e){}
System.out.println(Thread.currentThread().getName()+"sale"+num--);
}
}
this.show();}
}
}else{
while (true){
show();
}
}
public synchronized void show(){
if(num>0){
try{
Thread.sleep(10);
}catch (Exception e){}
System.out.println(Thread.currentThread().getName()+"sale"+num--);
}
}
}}
class ThisLockDemo{
public static void main(String[] args){
Ticket t=new Ticket();
Thread t1= new Thread(t);
Thread t2=new Thread(t);
t1.start();
t1.flag=true;
t2.start();
}
}
- 如果同步函数被静态修饰后,使用的锁是什么呢?
通过发现,不是在是this,因为静态方法也不可以定义this,静态进内存是,内存中没有本类对象,但是一定有该类对应额字节码文件对象;
类名,class,该对象的类型是Class;
静态同步方法,使用的锁是该方法,所在类字节码文件对象,类名class;
class Ticket implements Runnable{
private int num=1000;
boolean flag =true;
public void run(){
if (flag){
while(true){
synchronized(Ticket.class){
if(num>0){
try{
Thread.sleep(10);
}catch (Exception e){}
System.out.println(Thread.currentThread().getName()+"sale"+num--);
}
}
this.show();}
}
}else{
while (true){
show();
}
}
public synchronized void show(){
if(num>0){
try{
Thread.sleep(10);
}catch (Exception e){}
System.out.println(Thread.currentThread().getName()+"sale"+num--);
}
}
}}
class ThisLockDemo{
public static void main(String[] args){
Ticket t=new Ticket();
Thread t1= new Thread(t);
Thread t2=new Thread(t);
t1.start();
t1.flag=true;
t2.start();
}
}
死锁:
同步中嵌套同步,而锁确不同;
class Ticket implements Runnable{
private int num=1000;
Object obj=new Object();
boolean flag =true;
public void run(){
if (flag){
while(true){
synchronized(obj){
if(num>0){
try{
Thread.sleep(10);
}catch (Exception e){}
System.out.println(Thread.currentThread().getName()+"sale"+num--);
}
}
this.show();}
}
}else{
while (true){
show();
}
}
public synchronized void show(){
synchronized(obj){
if(num>0){
try{
Thread.sleep(10);
}catch (Exception e){}
System.out.println(Thread.currentThread().getName()+"sale"+num--);
}
}
}}
class ThisLockDemo{
public static void main(String[] args){
Ticket t=new Ticket();
Thread t1= new Thread(t);
Thread t2=new Thread(t);
t1.start();
t1.flag=true;
t2.start();
}
}
java学习之- 线程运行状态的更多相关文章
- Java学习笔记 线程池使用及详解
有点笨,参考了好几篇大佬们写的文章才整理出来的笔记.... 字面意思上解释,线程池就是装有线程的池,我们可以把要执行的多线程交给线程池来处理,和连接池的概念一样,通过维护一定数量的线程池来达到多个线程 ...
- java学习之线程
一.线程总述: 线程是java当中一个重要的内容,如果想说线程的话,那我们应该先来讲一下什么是进程. 进程:那么什么是进程呢,进程从字面上来理解就是,正在进行的程序.就比如说我们在windows当中打 ...
- java学习之线程池的实现
package com.gh.threadpoor; import java.util.concurrent.ExecutorService; import java.util.concurrent. ...
- Java 学习笔记 线程控制
题目一 本质上来说,线程是不可控制的,线程的执行是由CPU资源分配决定的,我们无法干预系统CPU的资源分配,但我们可以增加条件来让线程按照我们的预想顺序来执行. 比如.如果当前的执行的线程不满足我们所 ...
- java学习之- 线程继承Thread类
标签(空格分隔): 线程 在java.lang包中有个Thread子类,大家可以自行查阅文档,及范例: 如何在自定义的代码中,自定义一个线程呢? 1.通过对api的查找,java已经提供了对线程这类事 ...
- Java学习:线程池
线程池 线程池概念:其实就是一个容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象的操作,无需反复创建线程而消耗过多的资源. 线程池:容器-->集合(ArrayList,Hash ...
- Java学习:线程的安全问题
线程的安全问题 模拟卖票案例创建三个的线程,同时开启,对共享的票进行出售 public class RunnableImpl implementsc Runnable{ //定义一个多线程共享的票源 ...
- Java学习:线程实现方式
线程实现方式 并发与并行 并发:指两或多个事件在同一个时间段内发生 并行:指两或多个事件在同一个时刻发生(同时发生) 进程的概念 内存:所有的应用程序都需要进入到内存中执行 临时存储RAM 硬盘:永久 ...
- java学习笔记 - 线程池(一)
线程池(Thread Pool):把一个或多个线程通过统一的方式进行调度和重复使用的技术,避免了因为线程过多而带来使用上的开销 优点:(面试题)可重复使用已有线程,避免对象创建.消亡和过度切换的性能开 ...
随机推荐
- nginx(二)
nginx rewrite Nginx提供的全局变量或自己设置的变量,结合正则表达式和标志位实现url重写以及重定向.rewrite只能放在server{},location{},if{}中,并且 ...
- 关于C#多线程、易失域、锁的分享
一.多线程 windows系统是一个多线程的操作系统.一个程序至少有一个进程,一个进程至少有一个线程.进程是线程的容器,一个C#客户端程序开始于一个单独的线程,CLR(公共语言运行库)为该进程创建了一 ...
- lr参数化
为什么做参数化? 数据库校验:注册用户时会看数据库有没有这个账号 应用程序校验:pc端qq登陆,一个账号只能登陆一台电脑 1.数据库或应用程序提交值的唯一性校验 数据库查询过程: 1.语法检查.语义检 ...
- 如何实现Excel多人共享与协作
1.写在前面的话 本人从事信息化工作多年,对Excel等电子表格的多人共享与协作接触较早,帮助客户实施的方案也较多,因此有些体会和认识.正好看到网上这方面的讨论较多,但都不完整,我就进一步做了专题调研 ...
- Java基础之十五 泛型
第十五章 泛型 一般的类和方法,只能使用具体的类型:要么是基本类型,要么是自定义类型.如果要编写可以应用于多种类型的代码,这种刻板的限制对代码的束缚就会很大. 在面对对象编程语言中,多态算是一种泛化机 ...
- Android开发——通过wifi接收IPCamera视频流
前面,我们已经了解了怎么在android app上打开关闭和扫描,搜索wifi,现在,我来写一下怎么通过连接wifi来使app获取到IPCamera摄像头的视频. 一.通过URL获取视频的地址 二.创 ...
- 抓取崩溃的log日志
1.下载adb工具包 也就是解锁软件,如果要解锁的话,需确认有fastboot 安装jdk.sdk 2.注意事项 请确保电脑上只连接了一台手机设备(最好只连接一条USB线),同时确保手机已开启USB调 ...
- 03-Django模型类
ORM框架:对象-关系-映射 将面向对象语言程序中的对象自动持久化到关系数据库中.本质就是将数据从一种形式转换到另外一种形式O表示Object 对象类R表示Relations 关系,关系数据库中的表M ...
- 用机智云做PWM占空比控制电机,物联网智能家居应用
因为是新申请的博客,所以申请了总想往里面加点东西,所以把我之前在机智云写的帖子复制了过来 (各位抱歉,由于之前上传的文件可能有错误,之前上传的文件PWM不能用,那么我又重新上传了一个文件,这个文件 ...
- java并发之ConcurrentLinkedQueue
在并发编程中,我们可能经常需要用到线程安全的队列,JDK提供了两种模式的队列:阻塞队列和非阻塞队列.阻塞队列使用锁实现,非阻塞队列使用CAS实现.ConcurrentLinkedQueue是一个基于链 ...