• 【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. /*
    2. * 出现线程安全解决方式:
    3. * 方式一:
    4. * 1、同步代码块;
    5. * synchronized(同步代码块){
    6. * //需要被同步的代码
    7. * }
    8. */
    9. class window1 implements Runnable{
    10. private int ticket = 100;
    11. Object obj = new Object();
    12. @Override
    13. public void run() {
    14. while(true){
    15. // 这里也可以使用this,需要把obj的创建对象删除,在把synchronized()括号里替换成this
    16. synchronized(obj) {
    17. if (ticket > 0) {
    18. // 出现线程安全
    19. try {
    20. Thread.sleep(100);
    21. } catch (InterruptedException e) {
    22. e.printStackTrace();
    23. }
    24. System.out.println(Thread.currentThread().getName() + "卖票,剩余票数:" + ticket);
    25. ticket--;
    26. } else {
    27. break;
    28. }
    29. }
    30. }
    31. }
    32. }
    33. public class Test1 {
    34. public static void main(String[] args) {
    35. window1 wd = new window1();
    36. Thread t1=new Thread(wd);
    37. Thread t2=new Thread(wd);
    38. Thread t3=new Thread(wd);
    39. t1.setName("窗口一");
    40. t2.setName("窗口二");
    41. t3.setName("窗口三");
    42. t1.start();
    43. t2.start();
    44. t3.start();
    45. }
    46. }
    1. /**
    2. * 方式二:
    3. * 使用同步方法解决实现Runnable接口的线程安全问题
    4. * 代码的执行放在另一个方法中,声明的方式的返回值是synchronized
    5. *
    6. */
    7. class window2 implements Runnable{
    8. private int ticket = 100;
    9. @Override
    10. public void run() {
    11. while(true){
    12. show();
    13. }
    14. }
    15. private synchronized void show(){
    16. // 或者使用同步代码块:synchronized (this) {
    17. if (ticket > 0) {
    18. try {
    19. Thread.sleep(100);
    20. } catch (InterruptedException e) {
    21. e.printStackTrace();
    22. }
    23. System.out.println(Thread.currentThread().getName() + "卖票,剩余票数:" + ticket);
    24. ticket--;
    25. }
    26. }
    27. }
    28. public class Test2 {
    29. public static void main(String[] args) {
    30. window2 wd = new window2();
    31. Thread t1=new Thread(wd);
    32. Thread t2=new Thread(wd);
    33. Thread t3=new Thread(wd);
    34. t1.setName("窗口一");
    35. t2.setName("窗口二");
    36. t3.setName("窗口三");
    37. t1.start();
    38. t2.start();
    39. t3.start();
    40. }
    41. }

    同步方法改进:

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

    1. class Bank {
    2. private Bank() {
    3. }
    4. private static Bank instance = null;
    5. public static Bank getInstance() {
    6. // 方式一:效率差
    7. // synchronized (Bank.class) {
    8. // if (instance == null) {
    9. // instance = new Bank();
    10. // }
    11. // return instance;
    12. // }
    13. // 方式二:效率高一点
    14. if (instance == null) {
    15. //Bank.class:是代表当前类
    16. synchronized (Bank.class) {
    17. if (instance == null) {
    18. instance = new Bank();
    19. }
    20. return instance;
    21. }
    22. }
    23. return null;
    24. }
    25. }

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

    1. class Window4 implements Runnable{
    2. private int ticket =100;
    3. // 1、实例化lock
    4. private ReentrantLock lock=new ReentrantLock(true);
    5. @Override
    6. public void run() {
    7. while(true){
    8. try {
    9. // 2、调用锁定方法lock();
    10. lock.lock();
    11. if (ticket > 0) {
    12. try {
    13. Thread.sleep(100);
    14. } catch (InterruptedException e) {
    15. e.printStackTrace();
    16. }
    17. System.out.println(Thread.currentThread().getName() + "销售为:" + ticket);
    18. ticket--;
    19. } else {
    20. break;
    21. }
    22. }finally {
    23. // 3、调用解锁方法:unlock()
    24. lock.unlock();
    25. }
    26. }
    27. }
    28. }
    29. public class Test5 {
    30. public static void main(String[] args) {
    31. Window4 window=new Window4();
    32. Thread t1=new Thread(window);
    33. Thread t2=new Thread(window);
    34. Thread t3=new Thread(window);
    35. t1.setName("窗口一");
    36. t2.setName("窗口二");
    37. t3.setName("窗口三");
    38. t1.start();
    39. t2.start();
    40. t3.start();
    41. }
    42. }

    方式三修改

    1. **
    2. * 创建线程的方式三:实现collable接口的方式。----JDK 5.0新增
    3. * callable接口的方式创建多线程比Runnable接口创建多线程方式强大?
    4. * 1、call()可以有返回值
    5. * 2、call()可以抛出异常,被外面的操作捕获,获取异常的信息
    6. * 3、callable是支持泛型的
    7. * Description:
    8. * @author: ----千里之行,始于足下----
    9. * date: 2022/8/15 15:12
    10. */
    11. //1、创建一个实现callable的实现类
    12. class NumThread implements Callable{
    13. //2、实现call方法,将此线程需要执行的操作声明在call()中
    14. @Override
    15. public Object call() throws Exception {
    16. int sum=0;
    17. for (int i = 1; i <= 100; i++) {
    18. if(i%2==0){
    19. System.out.println(i);
    20. sum+=i;
    21. }
    22. }
    23. return sum;
    24. }
    25. }
    26. public class ThreadNew {
    27. public static void main(String[] args) {
    28. //3、创建callable接口实现类的对象
    29. NumThread numThread =new NumThread();
    30. //4、将此callable接口实现类的对象作为传递到FutureTask构造器中,创建FutureTask的对象
    31. FutureTask futureTask =new FutureTask(numThread);
    32. //5、将FutureTask的对象作为参数传递到Thread类的构造器中,创建Thread对象,并调用start()
    33. new Thread(futureTask).start();
    34. try {
    35. // 6、获取callable中call方法的返回值
    36. // get()返回值即为FutureTask构造器参数Callable实现类重写的call()的返回值。
    37. Object sum = futureTask.get();
    38. System.out.println(sum);
    39. } catch (InterruptedException e) {
    40. e.printStackTrace();
    41. } catch (ExecutionException e) {
    42. e.printStackTrace();
    43. }
    44. }
    45. }

  • 相关阅读:
    Rocketmq的集群搭建
    【一步到位】Jenkins的安装、部署、启动(完整教程)
    写给自己:入职两个月的收获与变化
    内置函数和消息传递API
    Apache shiro框架
    【中间件篇-Redis缓存数据库02】Redis高级特性和应用(慢查询、Pipeline、事务、Lua)
    客户端负载均衡策略:loadBalancer,ribbon
    51单片机项目(13)——基于51单片机的智能台灯protues仿真
    机试打卡 -05 接雨水(动态规划&栈)
    一位程序员感慨:互联网行业太过共享,才导致了门槛越来越低
  • 原文地址:https://blog.csdn.net/fool_Java/article/details/126896265