【Day22】解决线程安全问题以及JDK1.5新增

 

目录

 总体框架:

同步方法改进:

使用同步机制将单例模式中的懒汉式更改为线程安全的

 解决线程问题的方式三:Lock锁-----JDK5.0新增

方式三修改


总体框架:

/**
 *    题目:三个窗口售票,总票数100张,售完为止
 *
 * 出现线程安全解决方式:
 * 方式一:
 * 1、同步代码块;
 *  synchronized(同步代码块){
 *      //需要被同步的代码
 *  }
 *  说明:1、操作共享数据的代码,即为需要被同步的代码
 *       2、共享数据:多个线程共同操作的变量,比如:ticket就是共享数据。
 *       3、同步监视器,俗称:锁。任何一个类都可以充当一把锁。
 *          要求:多个线程必须用同意把锁
 *
 * 2、this
 *  synchronized(this){  //this表示当前对象,且当前对象只有一个
 *
 *  }
 * 3、当前类.class充当,类只会加载一次
 *  synchronized(当前类.class){
 *
 *  }
 *
 *  方式二:同步方法
 *  如果操作共享数据的代码完整的声明在一个方法中国,我们不妨将此方法声明同步的
 *  同步代码块总结:
 * 1、同步方法仍涉及到同步监控器,只是不愿要我们显示声明
 * 2、非静态的同步方式,同步监控器是:this
 *      静态的同步方式,同步监控器是当前类本身
 *
 *
 *使用同步机制将单例模式中的懒汉式更改为线程安全的
 *
 *
 * 解决线程问题的方式三:Lock锁-----JDK5.0新增
 * 1、实例化lock
 * 2、调用锁定方法lock()
 * 3、调用解锁方法:unlock()
 */
 /*
 * 出现线程安全解决方式:
 * 方式一:
 * 1、同步代码块;
 *  synchronized(同步代码块){
 *      //需要被同步的代码
 *  }
 */


class window1 implements Runnable{
    private int ticket = 100;
    Object obj = new Object();
    @Override
    public void run() {
        while(true){
//            这里也可以使用this,需要把obj的创建对象删除,在把synchronized()括号里替换成this
            synchronized(obj) {
                if (ticket > 0) {
//                出现线程安全
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "卖票,剩余票数:" + ticket);
                    ticket--;
                } else {
                    break;
                }
            }
        }
    }
}

public class Test1 {
    public static void main(String[] args) {

        window1 wd = new window1();
        Thread t1=new Thread(wd);
        Thread t2=new Thread(wd);
        Thread t3=new Thread(wd);

        t1.setName("窗口一");
        t2.setName("窗口二");
        t3.setName("窗口三");

        t1.start();
        t2.start();
        t3.start();
    }
}
/**
 * 方式二:
 * 使用同步方法解决实现Runnable接口的线程安全问题
 * 代码的执行放在另一个方法中,声明的方式的返回值是synchronized
 *
*/
class window2 implements Runnable{
    private int ticket = 100;
    @Override
    public void run() {
        while(true){
            show();

        }

    }
    private synchronized void show(){ 
//        或者使用同步代码块:synchronized (this) {
            if (ticket > 0) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "卖票,剩余票数:" + ticket);
                ticket--;
            }
    }
}
public class Test2 {
    public static void main(String[] args) {

        window2 wd = new window2();
        Thread t1=new Thread(wd);
        Thread t2=new Thread(wd);
        Thread t3=new Thread(wd);

        t1.setName("窗口一");
        t2.setName("窗口二");
        t3.setName("窗口三");

        t1.start();
        t2.start();
        t3.start();
    }
}

同步方法改进:

使用同步机制将单例模式中的懒汉式更改为线程安全的

class Bank {
    private Bank() {
    }

    private static Bank instance = null;

    public static Bank getInstance() {

//        方式一:效率差
//        synchronized (Bank.class) {
//            if (instance == null) {
//                instance = new Bank();
//            }
//            return instance;
//        }


//        方式二:效率高一点
        if (instance == null) {
            //Bank.class:是代表当前类
            synchronized (Bank.class) {
                if (instance == null) {
                    instance = new Bank();
                }
                return instance;
            }
        }
        return null;
    }
}

 解决线程问题的方式三:Lock锁-----JDK5.0新增

class Window4 implements Runnable{
    private int ticket =100;

//    1、实例化lock
    private ReentrantLock lock=new ReentrantLock(true);
    @Override
    public void run() {
        while(true){
            try {
//                2、调用锁定方法lock();
                lock.lock();

                if (ticket > 0) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "销售为:" + ticket);
                    ticket--;
                } else {
                    break;
                }
            }finally {
//                3、调用解锁方法:unlock()
                lock.unlock();
            }
        }
    }
}

public class Test5 {

    public static void main(String[] args) {
        Window4 window=new Window4();

        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();



    }
}

方式三修改

**
 * 创建线程的方式三:实现collable接口的方式。----JDK 5.0新增
 * callable接口的方式创建多线程比Runnable接口创建多线程方式强大?
 * 1、call()可以有返回值
 * 2、call()可以抛出异常,被外面的操作捕获,获取异常的信息
 * 3、callable是支持泛型的
 * Description:
 * @author: ----千里之行,始于足下----
 * date: 2022/8/15  15:12
*/
//1、创建一个实现callable的实现类
class NumThread implements Callable{
    //2、实现call方法,将此线程需要执行的操作声明在call()中
    @Override
    public Object call() throws Exception {
        int sum=0;
        for (int i = 1; i <= 100; i++) {
            if(i%2==0){
                System.out.println(i);
                sum+=i;
            }
        }
        return sum;
    }
}
public class ThreadNew {
    public static void main(String[] args) {
        //3、创建callable接口实现类的对象
        NumThread numThread =new NumThread();
        //4、将此callable接口实现类的对象作为传递到FutureTask构造器中,创建FutureTask的对象
        FutureTask futureTask =new FutureTask(numThread);
        //5、将FutureTask的对象作为参数传递到Thread类的构造器中,创建Thread对象,并调用start()
        new Thread(futureTask).start();

        try {
//            6、获取callable中call方法的返回值
//            get()返回值即为FutureTask构造器参数Callable实现类重写的call()的返回值。
            Object sum = futureTask.get();
            System.out.println(sum);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }


    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

「已注销」

老板大气,I am happy

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值