(27)线程安全的实际应用

1,   同步方法
2,   同步代码块
3,   使用Lock锁
4,   比较同步方法,同步代码块和Lock锁的区别

如何解决线程安全的问题

1,同步方法,具体实现如下:
 public static void main(String[] args) {
        //定义三个线程分别开始购物
        Window window = new Window();
        Thread t1 = new Thread(window);
        Thread t2 = new Thread(window);
        Thread t3 = new Thread(window);
        t1.setName("拼夕夕");
        t2.setName("京东");
        t3.setName("淘宝");
        t1.start();
        t2.start();
        t3.start();
    }
}

class Window implements Runnable{
    //一共有1w块钱,拼夕夕上每次购物50元,京东上每次购物300,淘宝每次购物150
    private int money = 10000;

    @Override
    public void run() {
        while (true){
            if(money > 0) {
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (money>0){
                    pay();
                }else {
                    break;
                }
            }else {
                break;
            }
        }
    }

    public synchronized void pay(){
        System.out.print(Thread.currentThread().getName()+":购了一次物");
        if(Thread.currentThread().getName().equals("拼夕夕")){
            money -= 50;
        }
        if(Thread.currentThread().getName().equals("京东")){
            money -= 300;
        }
        if(Thread.currentThread().getName().equals("淘宝")){
            money -= 150;
        }
        System.out.println("剩余的钱为"+money);
    }
2,同步代码块,具体实现如下:
  public static void main(String[] args) {
        //定义三个线程分别开始卖票
        Window window = new Window();
        Thread t1 = new Thread(window);
        Thread t2 = new Thread(window);
        Thread t3 = new Thread(window);
        t1.setName("飞猪");
        t2.setName("12306");
        t3.setName("携程");
        t1.start();
        t2.start();
        t3.start();
    }
}
class Window implements Runnable{
    //一共有100张票
    private int ticket = 100;
    @Override
    public void run() {
        while (true) {
            synchronized (this) { //this为Window对象
                if (ticket > 0) {
                    try {
                        Thread.sleep(300);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "卖了一张票,票号为" + ticket);
                    ticket--;
                } else {
                    break;
                }
            }
        }
    }
3,使用Lock锁,具体实现如下:
class Window implements Runnable{
    //一共有100张票
    private int ticket = 100;
    //声明锁
    private Lock lock = new ReentrantLock();

    @Override
    public void run() {
        while (true) {
            lock.lock();//加锁
            if (ticket > 0) {
                try {
                    Thread.sleep(300);
                    System.out.println(Thread.currentThread().getName() + "卖了一张票,票号为" + ticket);
                    ticket--;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    lock.unlock();//释放锁
                }
            } else {
                lock.unlock();//释放锁
                break;
            }
        }
    }

比较同步方法,同步代码块和Lock锁的区别

1,同步方法:synchronized关键字修饰的方法, 当用此关键字修饰方法时,
内置锁会保护整个方法。在调用该方法前,需要获得内置锁,否则就处于阻塞状态。

2,同步代码块:synchronized关键字修饰的代码块。 被该关键字修饰的语句块会自动被加上内置锁,从而实现同步。

3,一般情况下,尽量使用同步代码块,减少同步的内容。

4,Lock锁:在jdk1.5中新增了一个java.util.concurrent包来支持同步。 ReentrantLock类是可重入、互斥、实现了Lock接口的锁, 它的功能在synchronized的继承上扩展了其能力,要注意释放锁。

5,这三种方法都实现了线程的同步。


下一章,(28)Java中泛型和File类的使用

发布了67 篇原创文章 · 获赞 19 · 访问量 9879

猜你喜欢

转载自blog.csdn.net/qq_41530004/article/details/103489648