线程安全,死锁..

复习

线程的概念

本质上就是一条执行路径

作用 : 使代码同时可以执行多个事物

(其实是线程之间的高频转换,不断的抢夺CPU执行权,抢到就有执行权,但有时间限制--时间片)

线程的相关名词

进程 : 一个正在进行的程序

线程 : 一条执行路径

每个线程都有自己的栈内存,

而多个线程共享一个堆内存

主线程 : 进程在开启时自带一个线程,该线程被称为主线程

子线程 : 除主线程外,其他线程都是子线程

多线程 : 一个进程中有多个线程

前台线程 : 线程默认为前台线程 一个进程中只要有前台线程存活,那么该进程就不会被系统所回收

(前台线程执行完,有一段时间的延迟,可以让后台进程执行一段)

守护线程(后台线程) : 使用方法对线程进行设置 一个进程中所有前台线程都被销毁,那么该进程将会被系统回收,此时不管是否有守护线程存活

线程的组成

CPU时间片 : 含义 : 线程获取到CPU执行权后,可执行的时间

内存 : 含义:线程在使用时占用的内存,一个线程一个栈,多个线程共享一个堆

逻辑 : 含义:编写线程执行时的代码顺序

线程的创建

方案1:创建Thread的子类对象

方式1:普通方式
    步骤:
        1,创建一个类
        2,使其继承与Thread
        3,重写run方法
        4,创建该类对象
方式2:使用匿名内部类创建Thread的子类对象(合并123步骤)
    步骤:
        Thread 对象名 = new Thread(){
            重写run方法
        };

方案2:将线程(Thread)与线程任务(Runnable)分开

方式1:普通方式
    步骤:
        1,创建一个类
        2,使其Runnable接口
        3,重写run方法
        4,创建该类对象
        5,创建Thread对象,并传入该类对象
方式2:使用匿名内部类的形式创建Runnable的子类对象
    步骤:
        1,使用匿名内部类创建Runnable的子类对象
            Runnable 对象名 = new Runnable(){
                重写run
            };
        2,创建Thread对象,并传入Runnable的对象
            Thread 对象名2 = new Thread(对象名);

线程的使用

启动

线程对象.start()

销毁

线程已经启动不受控制
线程在启动后,将执行run方法中的代码,当run中的代码执行完毕后,线程会等待被系统回收
所以想让线程提前结束,得想办法run中的代码提前执行完毕

名称

设置线程名称
    方式1:在创建线程对象时传入
    方式2:使用线程对象.setName进行设置,注意:在线程启动之前
获取线程名称
    String 线程名称 = 线程对象.getName();
​
注意:
    主线程名称为main
    子线程名称默认为:Thread-0,Thread-1,....

获取当前线程

Thread 当前线程对象 = Thread.currentThread();

优先级

作用:提高线程抢夺到CPU执行权的概率
设置优先级
	线程对象.setPriority(优先级);
	注意:
		优先级取值范围:1~10
获取优先级
	int 变量名 = 线程对象.getPriority();

休眠

作用:让线程停止执行,也不在抢夺CPU执行权
语法:
	Thread.sleep(休眠时间);

礼让

作用:让线程让出本次抢夺到的CPU执行权,然后重新参与抢夺
语法:
	Thread.yield();

合并

作用:将两个线程合并为一个线程
语法:
	线程对象.join();
注意:
	将线程对象所属的线程合并到当前线程,此时将先执行线程对象所属的线程剩余的代码,当执行完毕后,在执行当前线程剩余的代码

守护线程

语法:
	线程对象.setDaemon(true);

线程的生命周期

创建
就绪
运行
消亡
阻塞
等待
	无限期
	有限期

今日

线程安全问题

原因

多个线程操作同一个数据,会导致线程安全问题

解决思路

保证同时只能有一个线程操作该数据

方案一 : 同步代码块 锁对象就是自己建的

语法
	synchronized(锁对象){		
		要同步的代码		(同时操作的数据)
	}

注意 :

1.所有对象都可以作为锁对象 2.多个线程的锁对象要是同一个对象

方案二 : 同步方法 this(调用这个方法的对象就是锁对象)

语法
	访问权限修饰符 synchronized 返回值类型 方法名(形参列表){
	}
int a;
String b;
char c;
a.方法();		//此时a就是锁对象
...

注意 :

1.同步方法的锁对象是this 2.多个线程的锁对象要是同一个对象

方案三 : 同步静态方法 锁对象就是JVM加载的该类对象

类对象

JVM加载类时会生成一个对象,该对象就是该类的类对象,一个类只有一个类对象(因为类只会加载一次)

语法
	访问权限修饰符 synchronized static 返回值类型 方法名(形参列表){
	}

注意 :

1.同步静态方法的锁对象时该类的类对象 2.多个线程的锁对象要是同一个对象

死锁 (主动避免)

原因

多个线程互相持有对方所需的锁资源

例子

Object A = new Object();
Object B = new Object();	//创建两个对象,作为两把锁
线程1:
	xxx
	synchronized (A){		//锁A在外
		xxx
		synchronized (B){	//锁B在内
			xxx
		}
	}				//当启动两个线程,有一种可能是
					//线程1进入A锁中,线程2进入B锁中
					//此时不管谁抢到执行权,因为要进入下一个锁
					//但此时B锁被线程2占用,A锁被线程1占用,无法进入
线程2:
	xxx
	synchronized (B){		//锁B在外
		xxx
		synchronized (A){	//锁A在内
			xxx
		}
	}

避免的思路

不要在同步中使用同步

经常会说要在同步范围内,如何辨别

有synchronized就是同步的范围

线程间通讯

让两个线程之间通讯--->一般就是叫醒/休眠操作

注意

1,线程间通讯的方法由Object提供
2,只能在同步中使用
3,只能使用所在的同步的锁对象调用

唤醒 :

	notify():随机唤醒一个
	notifyAll():唤醒所有

注意 :

只能唤醒以同一个对象调用wait方法的线程

休眠 :

wait():无限期休眠
wait(int ms):有限期休眠,ms毫秒
wait(int ms,int ns):有限期休眠,更精准,ns纳秒

注意 :

参数就是休眠时间,ms毫秒,ns纳秒

wait与sleep的区别 :

1.wait在休眠期间会释放所持有的锁资源,sleep不会 2.wait必须在同步中使用,sleep没有限制 3.wait必须使用所在的同步的锁对象调用,sleep使用Thread类或Thread类的对象调用 4.wait由Object提供,sleep由Thread类提供

生产者与消费者模式

设计模式

作用:解决特定问题的思路
生产者与消费者模式解决的是进销存业务
生产
	无限生产
销售
	无限销售
工厂
	生产的方法
	出货的方法
库存数量
商品数量上限:100
商品数量下限:0

作业

1,整理笔记
2,使用两个线程一个线程打印大写字母,一个打印小写字母
	打印结果如:aAbBcC...
3,使用两个线程一个线程打印数字1~52,一个打印字母a~z
	打印结果如:12a34b56c...
4,使用代码讲述龟兔赛跑
5,写一个三线程死锁
6,生成者与消费者模式
7,一个生成手机的厂商,
	生成的手机型号为T3,颜色,随机从(红,黄,蓝,黑,银)中指定,CPU型号3980,手机屏幕大小7寸
	请使用代码模拟该厂商生成与销售
	其中生成工人有,张三,李四,王五
	销售工人有,小白,小红,小黑
	生产工人每2秒生产一个手机
	销售人员0~10秒销售一个手机
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值