• 王志成 201771010130《面向对象程序设计(java)》第17周学习总结


    第一部分:理论知识学习部分

    线程同步

    多线程并发运行不确定性问题解决方案:引入线 程同步机制,使得另一线程要使用该方法,就只 能等待。

    ⚫ 在Java中解决多线程同步问题的方法有两种:

    1.- Java SE 5.0中引入ReentrantLock类(P648页)。

    2.- 在共享内存的类方法前加synchronized修饰符。

    ……

    public synchronized static void sub(int m)

    ……

    解决方案一:锁对象与条件对象

    用ReentrantLock保护代码块的基本结构如下:

    myLock.lock();

    try {

       critical section

    } finally{

    myLock.unlock(); }

    有关锁对象和条件对象的关键要点:

    ➢ 锁用来保护代码片段,保证任何时刻只能有一 个线程执行被保护的代码。

    ➢ 锁管理试图进入被保护代码段的线程。

    ➢ 锁可拥有一个或多个相关条件对象。

    ➢ 每个条件对象管理那些已经进入被保护的代码 段但还不能运行的线程。

    解决方案二: synchronized关键字

    synchronized关键字作用:

    ➢ 某个类内方法用synchronized 修饰后,该方法被称为同步方法;

    ➢ 只要某个线程正在访问同步方法,其他线程欲要访问同步方法就被阻塞,直至线程从同步方法返回前唤醒被阻塞线程,其他线程方可能进入同步方法。

    ➢ 一个线程在使用的同步方法中时,可能根据问题的需要,必须使用wait()方法使本线程等待,暂时让出CPU的使用权,并允许其它线程使用这个同步方法。

    ➢ 线程如果用完同步方法,应当执行notifyAll()方 法通知所有由于使用这个同步方法而处于等待的 线程结束等待。

    第二部分:实验部分

    实验时间 2018-12-10

    1、实验目的与要求

    (1) 掌握线程同步的概念及实现技术; 

    (2) 线程综合编程练习

    2、实验内容和步骤

    实验1:测试程序并进行代码注释。

    测试程序1:

    1.在Elipse环境下调试教材651页程序14-7,结合程序运行结果理解程序;

    2.掌握利用锁对象和条件对象实现的多线程同步技术。

    复制代码
     1 package synch;
     2 
     3 import java.util.*;
     4 import java.util.concurrent.locks.*;
     5 
     6 /**
     7 一个银行有许多银行帐户,使用锁序列化访问 * @version 1.30 2004-08-01
     8  * @author Cay Horstmann
     9  */
    10 public class Bank
    11 {
    12    private final double[] accounts;
    13    private Lock bankLock;
    14    private Condition sufficientFunds;
    15 
    16    /**
    17     * 建设银行。
    18     * @param n 账号
    19     * @param initialBalance 每个账户的初始余额
    20     */
    21    public Bank(int n, double initialBalance)
    22    {
    23       accounts = new double[n];
    24       Arrays.fill(accounts, initialBalance);
    25       bankLock = new ReentrantLock();
    26       sufficientFunds = bankLock.newCondition();
    27    }
    28 
    29    /**
    30     * 把钱从一个账户转到另一个账户。
    31     * @param 从账户转账
    32     * @param 转到要转账的账户
    33     * @param 请允许我向你转达
    34     */
    35    public void transfer(int from, int to, double amount) throws InterruptedException
    36    {
    37       bankLock.lock();
    38       try
    39       {
    40          while (accounts[from] < amount)
    41             sufficientFunds.await();
    42          System.out.print(Thread.currentThread());
    43          accounts[from] -= amount;
    44          System.out.printf(" %10.2f from %d to %d", amount, from, to);
    45          accounts[to] += amount;
    46          System.out.printf(" Total Balance: %10.2f%n", getTotalBalance());
    47          sufficientFunds.signalAll();
    48       }
    49       finally
    50       {
    51          bankLock.unlock();
    52       }
    53    }
    54 
    55    /**
    56     * 获取所有帐户余额的总和。
    57     * @return 总余额
    58     */
    59    public double getTotalBalance()
    60    {
    61       bankLock.lock();
    62       try
    63       {
    64          double sum = 0;
    65 
    66          for (double a : accounts)
    67             sum += a;
    68 
    69          return sum;
    70       }
    71       finally
    72       {
    73          bankLock.unlock();
    74       }
    75    }
    76 
    77    /**
    78     * 获取银行中的帐户数量。
    79     * @return 账号
    80     */
    81    public int size()
    82    {
    83       return accounts.length;
    84    }
    85 }
    复制代码
    复制代码
     1 package synch;
     2 
     3 /**
     4  * 这个程序显示了多个线程如何安全地访问数据结构。
     5  * @version 1.31 2015-06-21
     6  * @author Cay Horstmann
     7  */
     8 public class SynchBankTest
     9 {
    10    public static final int NACCOUNTS = 100;
    11    public static final double INITIAL_BALANCE = 1000;
    12    public static final double MAX_AMOUNT = 1000;
    13    public static final int DELAY = 10;
    14    
    15    public static void main(String[] args)
    16    {
    17       Bank bank = new Bank(NACCOUNTS, INITIAL_BALANCE);
    18       for (int i = 0; i < NACCOUNTS; i++)
    19       {
    20          int fromAccount = i;
    21          Runnable r = () -> {
    22             try
    23             {
    24                while (true)
    25                {
    26                   int toAccount = (int) (bank.size() * Math.random());
    27                   double amount = MAX_AMOUNT * Math.random();
    28                   bank.transfer(fromAccount, toAccount, amount);
    29                   Thread.sleep((int) (DELAY * Math.random()));
    30                }
    31             }
    32             catch (InterruptedException e)
    33             {
    34             }            
    35          };
    36          Thread t = new Thread(r);
    37          t.start();
    38       }
    39    }
    40 }
    复制代码

    测试程序2:

    1.在Elipse环境下调试教材655页程序14-8,结合程序运行结果理解程序;

    2.掌握synchronized在多线程同步中的应用。

    复制代码
     1 package synch2;
     2 
     3 import java.util.*;
     4 
     5 /**
     6  * 具有多个使用同步原语的银行账户的银行。
     7  * @version 1.30 2004-08-01
     8  * @author Cay Horstmann
     9  */
    10 public class Bank
    11 {
    12    private final double[] accounts;
    13 
    14    /**
    15     * 建设银行。
    16     * @param n 账号
    17     * @param initialBalance 每个账户的初始余额
    18     */
    19    public Bank(int n, double initialBalance)
    20    {
    21       accounts = new double[n];
    22       Arrays.fill(accounts, initialBalance);
    23    }
    24 
    25    /**
    26     * 把钱从一个账户转到另一个账户。
    27     * @param 从账户转账
    28     * @param 转到要转账的账户
    29     * @param 请允许我向你转达
    30     */
    31    public synchronized void transfer(int from, int to, double amount) throws InterruptedException
    32    {
    33       while (accounts[from] < amount)
    34          wait();
    35       System.out.print(Thread.currentThread());
    36       accounts[from] -= amount;
    37       System.out.printf(" %10.2f from %d to %d", amount, from, to);
    38       accounts[to] += amount;
    39       System.out.printf(" Total Balance: %10.2f%n", getTotalBalance());
    40       notifyAll();
    41    }
    42 
    43    /**
    44     * 获取所有帐户余额的总和。
    45     * @return 总余额
    46     */
    47    public synchronized double getTotalBalance()
    48    {
    49       double sum = 0;
    50 
    51       for (double a : accounts)
    52          sum += a;
    53 
    54       return sum;
    55    }
    56 
    57    /**
    58     * 获取银行中的帐户数量。
    59     * @return 
    60     */
    61    public int size()
    62    {
    63       return accounts.length;
    64    }
    65 }
    复制代码
    复制代码
     1 package synch2;
     2 
     3 /**
     4  * 
     5  * 这个程序展示了多个线程如何使用同步方法安全地访问数据结构。
     6  * @version 1.31 2015-06-21
     7  * @author Cay Horstmann
     8  */
     9 public class SynchBankTest2
    10 {
    11    public static final int NACCOUNTS = 100;
    12    public static final double INITIAL_BALANCE = 1000;
    13    public static final double MAX_AMOUNT = 1000;
    14    public static final int DELAY = 10;
    15 
    16    public static void main(String[] args)
    17    {
    18       Bank bank = new Bank(NACCOUNTS, INITIAL_BALANCE);
    19       for (int i = 0; i < NACCOUNTS; i++)
    20       {
    21          int fromAccount = i;
    22          Runnable r = () -> {
    23             try
    24             {
    25                while (true)
    26                {
    27                   int toAccount = (int) (bank.size() * Math.random());
    28                   double amount = MAX_AMOUNT * Math.random();
    29                   bank.transfer(fromAccount, toAccount, amount);
    30                   Thread.sleep((int) (DELAY * Math.random()));
    31                }
    32             }
    33             catch (InterruptedException e)
    34             {
    35             }
    36          };
    37          Thread t = new Thread(r);
    38          t.start();
    39       }
    40    }
    41 }
    复制代码

    测试程序3:

    1.在Elipse环境下运行以下程序,结合程序运行结果分析程序存在问题;

    2.尝试解决程序中存在问题。

    复制代码
     1 package sdfsd;
     2 
     3 class Cbank
     4 {
     5      private static int s=2000;
     6      public   static void sub(int m)
     7      {
     8            int temp=s;
     9            temp=temp-m;
    10           try {
    11                  Thread.sleep((int)(1000*Math.random()));
    12                }
    13            catch (InterruptedException e)  {              }
    14               s=temp;
    15               System.out.println("s="+s);
    16           }
    17     }
    18 
    19 
    20 class Customer extends Thread
    21 {
    22   public void run()
    23   {
    24    for( int i=1; i<=4; i++)
    25      Cbank.sub(100);
    26     }
    27  }
    28 public class Thread3
    29 {
    30  public static void main(String args[])
    31   {
    32    Customer customer1 = new Customer();
    33   
    34    Customer customer2 = new Customer();
    35    customer1.start();
    36    customer2.start();
    37   }
    38 }
    复制代码

     改进

    复制代码
     1 package sdfsd;
     2 
     3 class Cbank
     4 {
     5      private static int s=2000;
     6      public  synchronized static void sub(int m)
     7      {
     8            int temp=s;
     9            temp=temp-m;
    10           try {
    11                  Thread.sleep((int)(1000*Math.random()));
    12                }
    13            catch (InterruptedException e)  {              }
    14               s=temp;
    15               System.out.println("s="+s);
    16           }
    17     }
    18 
    19 
    20 class Customer extends Thread
    21 {
    22   public void run()
    23   {
    24    for( int i=1; i<=4; i++)
    25      Cbank.sub(100);
    26     }
    27  }
    28 
    29 public class Thread3
    30 {
    31  public static void main(String args[])
    32   {
    33    Customer customer1 = new Customer();
    34   
    35    Customer customer2 = new Customer();
    36    customer1.start();
    37    customer2.start();
    38   }
    39 }
    复制代码

    实验2 编程练习

    利用多线程及同步方法,编写一个程序模拟火车票售票系统,共3个窗口,卖10张票,程序输出结果类似(程序输出不唯一,可以是其他类似结果)。

    Thread-0窗口售:第1张票

    Thread-0窗口售:第2张票

    Thread-1窗口售:第3张票

    Thread-2窗口售:第4张票

    Thread-2窗口售:第5张票

    Thread-1窗口售:第6张票

    Thread-0窗口售:第7张票

    Thread-2窗口售:第8张票

    Thread-1窗口售:第9张票

    Thread-0窗口售:第10张票

    复制代码
     1 public class Demo {
     2     public static void main(String[] args) {
     3         Mythread mythread = new Mythread();
     4         Thread ticket1 = new Thread(mythread);
     5         Thread ticket2 = new Thread(mythread);
     6         Thread ticket3 = new Thread(mythread);
     7         ticket1.start();
     8         ticket2.start();
     9         ticket3.start();
    10     }
    11 }
    12 
    13 class shoupiao implements Runnable {
    14     int ticket = 1;
    15     boolean flag = true;
    16 
    17     @Override
    18     public void run() {
    19         while (flag) {
    20             try {
    21                 Thread.sleep(500);
    22             } catch (InterruptedException e) {
    23                 // TODO Auto-generated catch block
    24                 e.printStackTrace();
    25             }
    26 
    27             synchronized (this) {
    28                 if (ticket <= 10) {
    29                     System.out.println(Thread.currentThread().getName() + "窗口售:第" + ticket + "张票");
    30                     ticket++;
    31                 }
    32                 if (ticket > 10) {
    33                     flag = false;
    34                 }
    35             }
    36         }
    37     }
    38 
    39 }
    复制代码

     第三部分:总结

      这可能就是本周的最后一次作业了,一个学期的JAVA学习也将告一段落,我受益匪浅,很感谢老师和学长的一路陪伴,给予我们知识和教导我们为人处世的道理,感谢学长,感谢老师。

  • 相关阅读:
    spring项目(springmvc)(多模块/单模块)maven打包引入第三方jar方式,使用scope:system配置systemPath编译,不用添加到本地仓库!
    Mysql 执行效率 性能综合贴
    前端Js框架 UI框架汇总 特性 适用范围 选择
    通用 正则表达式 C# (.NET)Regex 总结
    VSCode Node cannot launch program setting the 'outFiles' attribute might help
    CSS常见问题,定位技巧总结
    java 欢迎页 主页 设置为servlet的方法
    MSSQL Server 及 MSSQL Express版本 自动备份
    SQL Server 2008 R2 安装 下载
    mysql 日期计算集合
  • 原文地址:https://www.cnblogs.com/847118824wang/p/10164220.html
Copyright © 2020-2023  润新知