0302 线程状态、线程安全
线程状态
1、新建状态
2、受阻塞状态
3、运行状态
4、死亡状态
5、休眠状态
6、等待状态

线程安全
当多条线程共用一份资源的时候就睡产生线程安全,比如电影院我们有100张票,同时有三个渠道去卖这100张票,看一下案例思维图

我们来模拟一下这个场景
首先创建一个线程类 实现Runnable接口,并且重写run方法
public class Ticket implements Runnable{
private int num=100;
//卖票
public void run() {
while(true){
if(num>0){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"卖出了第"+num--+"张票");
}
}
}
}
创建一个测试类,创建三条线程去卖票
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();
}
根据运行结果会发现,会有第0张和第-1张 还有可能会出现多条线程卖同一张票的情况

这就出现了线程安全问题,解决这个线程安全的方法
1、同步代码块
2、同步方法
3、lock接口
用到的是Synchronized关键字
1、同步代码块格式
synchronized (锁对象) {
可能会产生线程安全问题的代码
}
同步代码块的锁对象可以是任意对象,但要保证该对象是唯一的
代码展示
public class Ticket02 implements Runnable{
private int num=100;
//定义一个锁对象
private Object obj=new Object();
//卖票
public void run() {
while(true){
synchronized (obj) {
if(num>0){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"卖出了第"+num--+"张票");
}
}
}
}
}
2、同步方法
格式:
public synchronized void method(){
可能会产生线程安全问题的代码
}
代码展示
public class Ticket03 implements Runnable{
private int num=100;
//卖票
public void run() {
while(true){
sale();
}
}
//同步方法
public synchronized void sale(){
if(num>0){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"卖出了第"+num--+"张票");
}
}
}
3、lock接口
在loc接口中有两个方法
(1)lock()获取锁
(2)unlock()释放锁
因为lock是个接口 那我们需要创建他的子类对象ReentrantLock去使用
代码展示
public class Ticket04 implements Runnable{
private int num=100;
//定义锁对象
private Lock lock=new ReentrantLock();
//卖票
public void run() {
while(true){
//获取锁
lock.lock();
if(num>0){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"卖出了第"+num--+"张票");
}
//释放锁
lock.unlock();
}
}
}
那我们回想一下StringBuffer和StringBuilder这两个类完全相同,唯一的区别是StringBuilder比StringBuffer速度要快,是因为StringBuffer底层方法都用了Synchronized关键字,也就是说StringBuffer类能够保证线程安全,但StringBuilder类是不保证线程安全的,所以StringBuilder类适合在单线程中使用。

浙公网安备 33010602011771号