201771010126 王燕《面向对象程序设计(Java)》第十七周学习总结

实验十七  线程同步控制

实验时间 2018-12-10

1、实验目的与要求

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

? 多线程并发运行不确定性问题解决方案: 多线程并发运行不确定性问题解决方案: 多线程并发运行不确定性问题解决方案: 多线程并发运行不确定性问题解决方案: 多线程并发运行不确定性问题解决方案: 多线程并发运行不确定性问题解决方案: 多线程并发运行不确定性问题解决方案: 多线程并发运行不确定性问题解决方案: 多线程并发运行不确定性问题解决方案: 多线程并发运行不确定性问题解决方案: 多线程并发运行不确定性问题解决方案: 多线程并发运行不确定性问题解决方案: 多线程并发运行不确定性问题解决方案: 多线程并发运行不确定性问题解决方案: 多线程并发运行不确定性问题解决方案: 多线程并发运行不确定性问题解决方案: 多线程并发运行不确定性问题解决方案: 多线程并发运行不确定性问题解决方案: 引入线 引入线 引入线 程同步机制 程同步机制 程同步机制 程同步机制 程同步机制 ,使得另一线程要用该方法 使得另一线程要用该方法 使得另一线程要用该方法 使得另一线程要用该方法 使得另一线程要用该方法 使得另一线程要用该方法 使得另一线程要用该方法 使得另一线程要用该方法 使得另一线程要用该方法 使得另一线程要用该方法 使得另一线程要用该方法 使得另一线程要用该方法 ,就只 能等待 。
? 在Java 中解决多线程同步问题 的方法有两种: 的方法有两种: 的方法有两种: 的方法有两种: 的方法有两种: 的方法有两种: 的方法有两种:
-Java SE 5.0中引入 ReentrantLock ReentrantLock ReentrantLockReentrantLock ReentrantLock类(P 648648648页)。
-在共享内存的类方法前加 在共享内存的类方法前加 在共享内存的类方法前加 在共享内存的类方法前加 在共享内存的类方法前加 在共享内存的类方法前加 在共享内存的类方法前加 在共享内存的类方法前加 在共享内存的类方法前加 在共享内存的类方法前加 在共享内存的类方法前加 synchronizedsynchronizedsynchronized synchronized synchronized synchronizedsynchronized修饰符 修饰符 修饰符 。

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

用ReentrantLock 保护代码块的基本结构如下:
myLock.lock myLock.lock myLock.lockmyLock.lock ();
try { try {try {try {
critical section critical section critical section critical section critical section }
finally{ finally{ finally{
myLock.unlock myLock.unlock myLock.unlockmyLock.unlock myLock.unlock (); (); (); (); }

有关锁对象和条件的键要点 有关锁对象和条件的键要点 :
? 锁用来保护代码片段 用来保护代码片段 用来保护代码片段 用来保护代码片段 用来保护代码片段 用来保护代码片段 用来保护代码片段 用来保护代码片段 ,保证任何时刻只能有一 保证任何时刻只能有一 保证任何时刻只能有一 保证任何时刻只能有一 保证任何时刻只能有一 保证任何时刻只能有一 保证任何时刻只能有一 保证任何时刻只能有一 保证任何时刻只能有一 保证任何时刻只能有一 个线程执行被保护的代码 。
? 锁管理试图进入被保护代码段的线程 管理试图进入被保护代码段的线程 。
? 锁可拥有一个或多相关 条件对象 条件对象 条件对象 条件对象 。
? 每个 条件对象管理 条件对象管理 条件对象管理 条件对象管理 条件对象管理 条件对象管理 那些已经进入被保护的代码 那些已经进入被保护的代码 那些已经进入被保护的代码 那些已经进入被保护的代码 那些已经进入被保护的代码 那些已经进入被保护的代码 那些已经进入被保护的代码 那些已经进入被保护的代码 那些已经进入被保护的代码 那些已经进入被保护的代码 那些已经进入被保护的代码 那些已经进入被保护的代码 段但还不能运行的线程 。

解决方案二: synchronized synchronized synchronized 关键字 关

synchronized 关键字作用:
? 某个类内方法用 某个类内方法用 某个类内方法用 某个类内方法用 某个类内方法用 某个类内方法用 某个类内方法用 synchronizedsynchronizedsynchronizedsynchronizedsynchronizedsynchronizedsynchronized synchronizedsynchronized synchronized修饰后 修饰后 修饰后 ,该方 法被称为同步方;
? 只要某个线程正在访问同步方法 只要某个线程正在访问同步方法 只要某个线程正在访问同步方法 只要某个线程正在访问同步方法 只要某个线程正在访问同步方法 只要某个线程正在访问同步方法 只要某个线程正在访问同步方法 只要某个线程正在访问同步方法 只要某个线程正在访问同步方法 只要某个线程正在访问同步方法 只要某个线程正在访问同步方法 只要某个线程正在访问同步方法 只要某个线程正在访问同步方法 只要某个线程正在访问同步方法 ,其他线程 其他线程 其他线程 其他线程 欲要访问同步方法就被阻塞 欲要访问同步方法就被阻塞 欲要访问同步方法就被阻塞 欲要访问同步方法就被阻塞 欲要访问同步方法就被阻塞 欲要访问同步方法就被阻塞 欲要访问同步方法就被阻塞 欲要访问同步方法就被阻塞 欲要访问同步方法就被阻塞 欲要访问同步方法就被阻塞 欲要访问同步方法就被阻塞 欲要访问同步方法就被阻塞 ,直至线程从同 直至线程从同 直至线程从同 直至线程从同 直至线程从同 直至线程从同 步方法返回前唤醒被阻塞线程 步方法返回前唤醒被阻塞线程 步方法返回前唤醒被阻塞线程 步方法返回前唤醒被阻塞线程 步方法返回前唤醒被阻塞线程 步方法返回前唤醒被阻塞线程 步方法返回前唤醒被阻塞线程 步方法返回前唤醒被阻塞线程 步方法返回前唤醒被阻塞线程 步方法返回前唤醒被阻塞线程 步方法返回前唤醒被阻塞线程 步方法返回前唤醒被阻塞线程 步方法返回前唤醒被阻塞线程 ,其他线程方 其他线程方 其他线程方 其他线程方 其他线程方 可能进入同步方法 。

在同步方法中使用 wait() wait()、notify notify notify 和notifyAll notifyAll notifyAllnotifyAll () 方法 (见教材 656 页

一个线程在使用的同步方法中时,可能根据问题 一个线程在使用的同步方法中时,可能根据问题 一个线程在使用的同步方法中时,可能根据问题 一个线程在使用的同步方法中时,可能根据问题 的需要,必须使用 wait() wait()方法使本线程等待,暂 方法使本线程等待,暂 方法使本线程等待,暂 方法使本线程等待,暂 方法使本线程等待,暂 方法使本线程等待,暂 方法使本线程等待,暂 方法使本线程等待,暂 方法使本线程等待,暂 方法使本线程等待,暂 时让出 CPU 的使用权,并允许其它线程这个 的使用权,并允许其它线程这个 的使用权,并允许其它线程这个 的使用权,并允许其它线程这个 的使用权,并允许其它线程这个 的使用权,并允许其它线程这个 的使用权,并允许其它线程这个 的使用权,并允许其它线程这个 的使用权,并允许其它线程这个 的使用权,并允许其它线程这个 的使用权,并允许其它线程这个 的使用权,并允许其它线程这个 的使用权,并允许其它线程这个 的使用权,并允许其它线程这个 的使用权,并允许其它线程这个 的使用权,并允许其它线程这个 同步方法。
? 线程如果用完同步方法,应当执行 线程如果用完同步方法,应当执行 notifyAll notifyAllnotifyAll () 方 法通知所有由于使用这个同步方而处等待的 法通知所有由于使用这个同步方而处等待的 法通知所有由于使用这个同步方而处等待的 法通知所有由于使用这个同步方而处等待的 线程结束等待。

(2) 线程综合编程练习

2、实验内容和步骤

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

测试程序1:

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

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

 1 package synch;
 2
 3 /**
 4  * This program shows how multiple threads can safely access a data structure.
 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 }

 1 package synch;
 2
 3 import java.util.*;
 4 import java.util.concurrent.locks.*;
 5
 6 /**
 7  * A bank with a number of bank accounts that uses locks for serializing access.
 8  * @version 1.30 2004-08-01
 9  * @author Cay Horstmann
10  */
11 public class Bank
12 {
13    private final double[] accounts;
14    private Lock bankLock;
15    private Condition sufficientFunds;
16
17    /**
18     * Constructs the bank.
19     * @param n the number of accounts
20     * @param initialBalance the initial balance for each account
21     */
22    public Bank(int n, double initialBalance)
23    {
24       accounts = new double[n];
25       Arrays.fill(accounts, initialBalance);
26       bankLock = new ReentrantLock();
27       sufficientFunds = bankLock.newCondition();
28    }
29
30    /**
31     * Transfers money from one account to another.
32     * @param from the account to transfer from
33     * @param to the account to transfer to
34     * @param amount the amount to transfer
35     */
36    public void transfer(int from, int to, double amount) throws InterruptedException
37    {
38       bankLock.lock();
39       try
40       {
41          while (accounts[from] < amount)
42             sufficientFunds.await();
43          System.out.print(Thread.currentThread());
44          accounts[from] -= amount;
45          System.out.printf(" %10.2f from %d to %d", amount, from, to);
46          accounts[to] += amount;
47          System.out.printf(" Total Balance: %10.2f%n", getTotalBalance());
48          sufficientFunds.signalAll();
49       }
50       finally
51       {
52          bankLock.unlock();
53       }
54    }
55
56    /**
57     * Gets the sum of all account balances.
58     * @return the total balance
59     */
60    public double getTotalBalance()
61    {
62       bankLock.lock();
63       try
64       {
65          double sum = 0;
66
67          for (double a : accounts)
68             sum += a;
69
70          return sum;
71       }
72       finally
73       {
74          bankLock.unlock();
75       }
76    }
77
78    /**
79     * Gets the number of accounts in the bank.
80     * @return the number of accounts
81     */
82    public int size()
83    {
84       return accounts.length;
85    }
86 }

测试程序2:

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

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

 1 package synch2;
 2
 3 import java.util.*;
 4
 5 /**
 6  * A bank with a number of bank accounts that uses synchronization primitives.
 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     * Constructs the bank.
16     * @param n the number of accounts
17     * @param initialBalance the initial balance for each account
18     */
19    public Bank(int n, double initialBalance)
20    {
21       accounts = new double[n];
22       Arrays.fill(accounts, initialBalance);
23    }
24
25    /**
26     * Transfers money from one account to another.
27     * @param from the account to transfer from
28     * @param to the account to transfer to
29     * @param amount the amount to transfer
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     * Gets the sum of all account balances.
45     * @return the total balance
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     * Gets the number of accounts in the bank.
59     * @return the number of accounts
60     */
61    public int size()
62    {
63       return accounts.length;
64    }
65 }

 1 package synch2;
 2
 3 import java.util.*;
 4
 5 /**
 6  * A bank with a number of bank accounts that uses synchronization primitives.
 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     * Constructs the bank.
16     * @param n the number of accounts
17     * @param initialBalance the initial balance for each account
18     */
19    public Bank(int n, double initialBalance)
20    {
21       accounts = new double[n];
22       Arrays.fill(accounts, initialBalance);
23    }
24
25    /**
26     * Transfers money from one account to another.
27     * @param from the account to transfer from
28     * @param to the account to transfer to
29     * @param amount the amount to transfer
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     * Gets the sum of all account balances.
45     * @return the total balance
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     * Gets the number of accounts in the bank.
59     * @return the number of accounts
60     */
61    public int size()
62    {
63       return accounts.length;
64    }
65 }

测试程序3:

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

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


class Cbank

{

private static int s=2000;

public   static void sub(int m)

{

int temp=s;

temp=temp-m;

try {

Thread.sleep((int)(1000*Math.random()));

}

catch (InterruptedException e)  {              }

s=temp;

System.out.println("s="+s);

}

}

class Customer extends Thread

{

public void run()

{

for( int i=1; i<=4; i++)

Cbank.sub(100);

}

}

public class Thread3

{

public static void main(String args[])

{

Customer customer1 = new Customer();

Customer customer2 = new Customer();

customer1.start();

customer2.start();

}

}

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

实验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 package shoupiao;
 2 public class Ticket implements Runnable {
 3     public int num = 0;
 4     Object obj = new Object();
 5     public void run() {
 6         while (true) {
 7             // 关键字后的小括号表示锁,锁可以是程序中的任意一个对象
 8             synchronized (obj) {
 9                 if (num >= 10) { //系统默认测试数据10张车票
10                      break;
11                 }
12                  try {
13                     // 当线程睡眠时锁不会开
14                    Thread.sleep(50);
15                 } catch (InterruptedException e) {
16                     e.printStackTrace();
17                }
18                num++;
19                 if(num<10){
20                     System.out.println(Thread.currentThread().getName() + "第"+num+"张票" );
21                 }else{
22                     System.out.println(Thread.currentThread().getName() + "第"+num+"张票" );
23                 }
24             }
25         }
26     }
27     public static void main(String[] args) {
28         Ticket ticket = new Ticket();
29         //1.创建购票线程
30         Thread t1 = new Thread(ticket, "Thread-0窗口售:");
31         Thread t2 = new Thread(ticket, "Thread-1窗口售:");
32         Thread t3 = new Thread(ticket, "Thread-2窗口售:");
33         //2.开启购票点(模拟3个线程)测试购票
34         System.out.println("---------------------------------");
35         System.out.println("售票系统");
36         System.out.println("---------------------------------");
37         System.out.println("系统当前在线剩余总票数:10张");
38         t1.start();
39         t2.start();
40         t3.start();
41     }
42  }

实验总结:通过对多线程的进一步学习,理解了线程中各种状态代表的含义,以及如何调用,运行的原理,理解和掌握了线程的优先级属性及调度方法,线程同步的概念及实现技术。通过多线程的运用,实现了多个程序同步运行,以及各个程序在运行期间各种状态如何合理有序的切换

原文地址:https://www.cnblogs.com/wy201771010126/p/10159183.html

时间: 2024-11-09 00:52:36

201771010126 王燕《面向对象程序设计(Java)》第十七周学习总结的相关文章

201777010217-金云馨《面向对象程序设计(Java)》第二周学习总结

项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p/11475377.html 作业学习目标 学习并掌握Java Application程序结构: 学习并掌握Java语言的数据类型与变量: 学会使用Java运算符构造各类表达式: 掌握Java Application输入输出技术: 掌握Java流程控制技术(分支.循环): 掌握Math类.Strin

201771010123汪慧和《面向对象程序设计Java》第二周学习总结

一.理论知识部分 1.标识符由字母.下划线.美元符号和数字组成, 且第一个符号不能为数字.标识符可用作: 类名.变量名.方法名.数组名.文件名等.第二部分:理论知识学习部分 2.关键字就是Java语言中已经被赋予特定意义 的一些单词. ?常见有:class.public.try.catch.if. float.import.void等. 关键字不做变量名. 3.Java有三种注释的方式:   // 注释内容由//一直到此行结束. /*和*/ 定义一个注释块.  /**开始,*/结束 这种注释方法

20182318 2019-2020-1 《数据结构与面向对象程序设计》第六周学习总结

20182318 2019-2020-1 <数据结构与面向对象程序设计>第六周学习总结 教材学习内容总结 第九章 多态 后绑定.效率低于编译阶段的绑定效率. 学习练习如何利用继承方式来实现多态性. 学习练习如何利用接口来实现多态性. 多态性设计(多个不同对象执行相同的基本行为,并且行为的不同实现方式取决于对象的具体类型.) 第十章 异常 异常处理(异常抛出的问题和处理异常的方法) 未捕获的异常. try-catch语句与finally子句. 异常传播.(就与传递性一样,举个例子:程序一存在异常

20182332 2019-2020-1 《数据结构与面向对象程序设计》第1周学习总结

20182332 2019-2020-1 <数据结构与面向对象程序设计>第1周学习总结1 教材学习内容总结 1.配置linux 虚拟机.java环境. 2.理解面向对象程序设计,包括属性.方法.封装等概念. Java基本结构,环境变量配置,集成开发环境. JAVA文件编译过程: 1.源文件由编译器编译成字节码(ByteCode) 2.字节码由java虚拟机解释运行. git命令: git init 创建本地版本库: git clone 与远程仓库建立联系: git add .将当前目录下文件添

《数据结构与面向对象程序设计》第1周学习总结

学号 2019-2020-2314 <数据结构与面向对象程序设计>第1周学习总结 教材学习内容总结 1.计算机系统是由软硬件组成的 2.java程序的结构组成(注释.标识符和保留字等) 注:java是大小写敏感的,大写和小写是有区别的 3.程序开发所包含的内容(程序设计语言的等级.编辑器.编译程序.解释程序.开发环境和语法语义) 4.在开发软件的过程中遇到问题时的解决步骤:理解问题.设计方案.考虑方案的选择并优化方案.实现方案.测试方案并修改存在的任何问题. 教材学习中的问题和解决过程 问题1

20182329 2019-2020-1 《数据结构与面向对象程序设计》第1周学习总结

20182329 2019-2020-1 <数据结构与面向对象程序设计>第1周学习总结 教材学习内容总结 git代码托管代码 Java的基本编程 jdb代码调试 教材学习中的问题和解决过程 问题1:在课本自学过程中,有一题是Java中有什么是不可能被识别的,我做错了一道(12345)可以被识别. 问题1解决方案:后来询问学长数字不与命令相匹配时不是有效的标识符,且标识符不能以数字为开头. 问题2:在自己对于课本代码编译时,发现自己main处显示错误 问题2解决方案:一开始我以为是我main的方

《数据结构与面向对象程序设计》第01周学习总结

目录 学号20182323 2019-2020-1 <数据结构与面向对象程序设计>第01周学习总结 教材学习内容总结 教材学习中的问题和解决过程 代码调试中的问题和解决过程 代码托管 上周考试错题总结 结对及互评 点评模板: 点评过的同学博客和代码 其他(感悟.思考等,可选) 学习进度条 参考资料 目录 学号20182323 2019-2020-1 <数据结构与面向对象程序设计>第01周学习总结 教材学习内容总结 学习了java的历史与发展. 学习了一些软件工具,开发环境等. 掌握

《数据结构与面向对象程序设计》第2-3周学习总结

学号20182329 2019-2020-1 <数据结构与面向对象程序设计>第2-3周学习总结 教材学习内容总结 条件语句和循环语句的使用 输入语句和输出语局应用 基本数据类型的转换和应用 各种类的使用方法,以及格式化输出的方法. 基本的类的编写 教材学习中的问题和解决过程 问题1:scanner输入时用short nextShort()输入时出现异常. 问题1解决方案:输入时应与前一项自己指定的数据类型一样才可以. 问题2:在应用impoet时使用import Java.util.*时并不会

20182320 2019-2020-1 《数据结构与面向对象程序设计》第4周学习总结

20182320 2019-2020-1 <数据结构与面向对象程序设计>第4周学习总结 1.教材学习内容总结 本周学习内容分为以下几个部分: 4.8.1 迭代器和for循环 5.1 再谈类和对象 5.2 类的剖析 5.3 封装 5.4 方法的剖析 5.5 静态类成员 5.6 类关系 5.7 方法设计 5.8 方法重载 5.9 测试 5.10 调试 4.8.1 迭代器和for循环 什么是迭代器? 迭代器是一个对象,我们可以使用它的方法来处理某集合中的元素,一次处理一个. 每个迭代器对象都有一个方

20182328 2019-2020-1 《数据结构与面向对象程序设计》第4周学习总结

20182328 2019-2020-1 <数据结构与面向对象程序设计>第4周学习总结 教材学习内容总结 1.对类和对象进一步的了解. 2.学习静态类和静态方法. 3.学习类之间不同类型的关系. 4.学习方法的设计及重载. 5.学习了如何调试. 教材学习中的问题和解决过程 问题1:为什么有的变量可以重名? 问题1解决方案:在方法内声明的局部变量可以和在类一级声明的实例变量有同样的名字. 问题2:方法重载的用处是什么? 问题2解决方案:方法可能面临会有不用的参数列表,这时会用到重载,方便调用.