Java学习第二十三天

Java学习第二十三天知识点(线程安全)

线程同步[线程安全]:
1.产生的原因: 多个线程共享一个资源
2.解决的办法: 使用同步锁(synchronized)
(1)同步方法锁:

	a.只能同时被一个线程所持有,当线程执行完这个方法的时候,才会将锁释放
	b.锁范围越大,效率越低
	c.锁在方法上,实际上锁的还是this对象上加锁
	d.锁普通方法: this对象上加锁
	  锁静态方法: 锁 类.class(类的字节码文件)对象

(2)同步代码块:

	a.可以将一部分代码加锁, 同步代码锁,需要借助一个对象
	b.加锁的对象: 可以是任意对象,只需要确保是多个线程所共享(对象是唯一的)
	c.一般来说都会使用this表示对象
	d.同步锁(对象锁),一个对象只能加一把锁,并且只能同时被一个线程所持有的
public void sale(){
        //同步代码块
        synchronized(this){
            System.out.println(Thread.currentThread().getName() + "正在售卖:" + sum--);
            if (sum == 0) {
                throw new RuntimeException("票已售空!");
                //System.out.println("票已售空!");
            }
        }
           System.out.println(1);


    }

3.Lock锁 - 接口
1).实现类 -> ReentreantLock(可重入锁)
2).API:
加锁: 锁对象.lock()
解锁: 锁对象.unlock()
3)乐观锁/悲观锁 -> 理解原理(使用场景)

ReentrantLock lock=new ReentrantLock();
    public void sale() {
        lock.lock();
        //同步代码块
        System.out.println(Thread.currentThread().getName() + "正在售卖:" + sum--);
        if (sum == 0) {
            throw new RuntimeException("票已售空!");

            //System.out.println("票已售空!");
        }
        lock.unlock();
        System.out.println(1);
    }

线程状态:
新建状态: new 一个对象
就绪状态:

a.通过调用start()进入就绪状态
b.run()就绪:  时间片到期,归还/调用yeild()

运行状态

a.cpu分配时间片进入到运行状态

阻塞状态(Blocked):

a.join() -> 造成别的线程阻塞
b.IO阻塞 -> 控制台输入/输出
c.计时等待 -> sleep(100)/wait(100)
d.无线等待 -> wait()/notifyAll()/notify()
e.锁阻塞 -> 加上同步锁/Lock锁

被终止状态: run()结束

join()测试代码:

public class LoadPicture {
    public static void main(String[] args) {
        Thread read = new Thread(){
            @Override
            public void run() {
                System.out.println("开始加载");
                for (int i = 0; i < 100; i++) {
                    System.out.println("进度"+(i+1));
                }
            }
        };

        Thread show = new Thread(){
            @Override
            public void run() {
                System.out.println("等待");
                try {
                    read.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("显示");
            }
        };
        read.start();
        show.start();


    }
}

线程通信:
1.两个线程有共享资源,并且线程之间有动作交互
2.实现: 使用wait() 和 notify()/notifyAll()
notify() -> 唤醒线程,每次中能唤醒一个线程,只能唤醒在等待的线程
notifyAll() -> 唤醒所有正在等待的线程

注意:wait() 和 notify 需要放在同一个锁中

线程安全测试代码:
loadImage :

public class loadImage extends Thread{
    public Picture pic;

    public loadImage(Picture pic) {
        this.pic=pic;
    }

    @Override
    public void run() {
        //加载图片
        for (int i = 0; i < 100; i++) {
            System.out.println("正在加载图片:"+(i+1)+"%");
        }
        System.out.println("图片加载完成!");
        pic.loadFlag=true;

        synchronized (pic){
            pic.notify();
        }

        //加载完后显示图片

        //显示完成后下载图片

        if (!pic.showFlag){
            synchronized (pic){
                try {
                    pic.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        System.out.println("图片下载开始");
        for (int i = 0; i < 100; i++) {
            System.out.println("正在下载图片:"+(i+1)+"%");
        }
        System.out.println("图片下载完成");
    }
}

showImage :

public class showImage extends Thread{
    public Picture pic;

    public showImage(Picture pic) {
        this.pic=pic;
    }

    @Override
    public void run() {
            System.out.println("等待图片加载完成...");
            //如果图片没加载完成那么等待

                if (!pic.loadFlag) {
                    synchronized (pic) {
                        try {
                            pic.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
                //如果图片加载完成后执行下面的程序
                    System.out.println("开始显示图片...");
                    System.out.println("图片显示完成");
                    pic.showFlag=true;
                synchronized (pic){
                            pic.notify();
                }


    }
}

class类:

public class Picture {
    public boolean loadFlag;
    public boolean showFlag;

}

主函数:

public class Main {
    public static void main(String[] args) {
        Picture pic = new Picture();

        loadImage li = new loadImage(pic);
        showImage si = new showImage(pic);

        li.start();
        si.start();

    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值