JAVA-SE多线程

根据上一个博客,我们还剩下一下内容:

多线程的死锁、线程的同步以及线程的通信问题

线程的死锁问题

死锁的理解:不同的线程分别占用对方的同步资源不放弃,都在等待对方放弃自己需要的同步资源,就形成了线程的死锁。

    说明:出现死锁的时候,不会出现异常,不会出现提示,只是所有线程都会处于阻塞状态,无法继续执行
        我们使用同步的时候,要避免死锁的出现。

/**
 * @Auther:Yuhai
 * @Date:2022/4/15-04-15-21:41
 * @Description:IntelliJ IDEA
 * @version:1.0
 */



/**
 *  死锁代码的演示
 *      造成死锁的原因:
 *          当一个线程拥有A对象锁,并等待B对象锁的时候,另一个线程拥有B对象锁,并等待A对象锁,这就造成了死锁。
 *  定义鞋的方向
 *  此时代码的演示中会发现小明和小红再抢一只鞋子,这就会出现死锁的状态,他们在抢同一个资源
 */
//定义鞋的方向
class Shoes{
    public static  String left = "leftShoes";
    public static  String right = "rightShoes";
}
//当两个线程都在强同一个资源时,就会出现线程的安全性问题,当然,如果一个两个线程都在同时等待彼此资源的释放,那么,就会出现死锁的状态,这是因为胡互不谦让的结果,
// 所以在实际开发当中,应避免这中操作的出现

public class DeadLock {

    public static void main(String[] args) {
        Runnable xaioming = new Runnable() {
            @Override
            public void run() {
                synchronized (Shoes.left){
                    System.out.println("小明拿到了左脚的鞋子");
                    synchronized (Shoes.right){
                        System.out.println("小明拿到了右脚鞋子,他可以穿鞋子走人了****");
                    }
                }
            }
        };

        Runnable xiaohong = new Runnable() {
            @Override
            public void run() {
                synchronized (Shoes.right){
                    System.out.println("小红拿到了右脚鞋子");
                    synchronized (Shoes.left){
                        System.out.println("小红拿到了左脚鞋子,也可以穿鞋子走人*******");
                    }
                }
            }
        };

        Thread thread1 =new Thread(xaioming,"小明");
        Thread thread2 =new Thread(xiaohong,"小红");


        thread1.start();
        thread2.start();
    }
}

如何解决线程的死锁问题:    尽量避免嵌套同步,减少同步资源的定义,专门的算法、原则

在我们的实际开发过程中,应当避免死锁的出现。

线程的同步问题:共享数据会出现线程的安全性问题。

我么可以使用同步代码块和同步方法来解决线程安全性问题

    同步代码块:简称锁
            synchronize(同步监视器)在实现Runnable接口的时候天生共享锁
            在thread中需要使用static对象和this关键字或者当前类的对象(对象.class)来充当锁

    同步方法:使用同步方法,对其方法进行synchronize关键字的修饰
              将同步代码块提取出来成为有一个方法,只需要将同步方法用synchronize修饰
             对于runnable接口实现多线程,只需要将同步的方法用static和synchronize修饰,因为独享不唯一

接下来列出一个简单的例子:

        四个窗口共卖100张票,保证每个窗口都可以卖票,不会抢占资源(这是使用同步方法来解决线程的安全性问题)

public class TicketImplements implements Runnable{
    int tick = 100;
    Object object = new Object();
    @Override
    public void run() {
        while (tick>0){
            //线程进来以后,遇到同步方法就只能进去一个线程
            Method();
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public synchronized void Method(){
        //判断一个票数的情况,如果票数大于零的情况下,就继续买票,进行减少的操作,
        if (tick>0){
            System.out.println(Thread.currentThread().getName()+"正在售卖第"+tick+"几张票");
            tick--;
        }
    }

    public static void main(String[] args) {
        TicketImplements t = new TicketImplements();
        new Thread(t, "窗口一").start();
        new Thread(t, "窗口二").start();
        new Thread(t, "窗口三").start();
        new Thread(t, "窗口四").start();

    }
}

线程的通信问题:我们可以在这里学到以下的几个方法

 wait():一旦执行此方法,当前线程就进入阻塞状态,并释放同步监视器
          notify(): 一旦执行此方法,就会唤醒wait()的一个线程,如果有多个wait,就会唤醒优先级最高的哪一个
          notifyAll():一旦执行此方法,就会唤醒所有的wait的程序
    说明:
        wait(),notify(),notifyAll()方法必须使用在同步方法或同步代码块中
        wait(),notify(),notifyAll()方法的调用必须是同步方法和同步代码块中的同步监视器。
        否则,会出现IllegalMonitsatreException 异常
        wait(),notify(),notifyAll()方法定义在java.lang.object类中

接下来举一个简单的例子:利用队列来演示的生产者与消费者的例子

/**
 * @Auther:Yuhai
 * @Date:2022/4/18-04-18-10:00
 * @Description:IntelliJ IDEA
 * @version:1.0
 */
/*
    共享数据源,商品的数据源。
 */
public class Goods {
    private String brand;
    private String name;

    public Goods(String brand, String name) {
        this.brand = brand;
        this.name = name;
    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
/**
 * @Auther:Yuhai
 * @Date:2022/4/18-04-18-10:02
 * @Description:IntelliJ IDEA
 * @version:1.0
 */
/*
    生产者生产产品。
 */
public class ProducerQueue implements Runnable {
    //阻塞队列
    private BlockingQueue<Goods> blockingQueue;

    public ProducerQueue(BlockingQueue<Goods> blockingQueue) {
        this.blockingQueue = blockingQueue;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            Goods goods = null;
            if (i%2 == 0){
                goods = new Goods("娃哈哈","矿泉水");

            }else{
                goods = new Goods("旺仔","小馒头");
            }
            System.out.println("生产者生产了产品-------"+goods.getBrand()+"-----"+goods.getName());
        //将商品放在队列中去
            try {
                blockingQueue.put(goods);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

以上是生产者

消费者

/**
 * @Auther:Yuhai
 * @Date:2022/4/18-04-18-10:10
 * @Description:IntelliJ IDEA
 * @version:1.0
 */
//消费者队列
public class ConsumerQueue implements Runnable {

    private BlockingQueue<Goods> blockingQueue;

    public ConsumerQueue(BlockingQueue blockingQueue) {
        this.blockingQueue = blockingQueue;
    }

    @Override
    public void run() {
        for (int i = 0; i <10 ; i++) {
            Goods goods = null;
            //从队列中取数据
            try {
                goods = blockingQueue.take();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("消费者消费了产品-------"+goods.getBrand()+"-------"+goods.getName());
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值