201871010119-帖佼佼《面向对象程序设计(java)》第十七周学习总结
博文正文开头格式:(2分)
| 
 项目  | 
 内容  | 
| 
 这个作业属于哪个课程  | 
 https://www.cnblogs.com/nwnu-daizh/  | 
| 
 这个作业的要求在哪里  | 
 https://www.cnblogs.com/nwnu-daizh/p/11435127.html  | 
| 
 作业学习目标  | 
 (1) 掌握菜单组件用途及常用API; (2) 掌握对话框组件用途及常用API; (3) 学习设计简单应用程序的GUI。  | 
随笔博文正文内容包括:
第一部分:总结线程同步技术(10分)
19、线程的同步:
多线程并发运行不确定性问题解决方案:
引入线程同步机制;
在Java中线程同步方法有两种:
(1)JavaSE5.0中引入ReentrantLock类;
20、有关锁对象和条件对象的关键要点:
锁用来保护代码片段,保证任何时刻只能有一个线程被保护执行的代码;
锁管理试图进入被保护的代码段的线程;
锁可拥有一个或多个相关的条件对象;
每个条件对象管理那些已经进入被保护得到代码段但还不能运行的线程;
21、在临界区中使用条件对象的await()、signal()、signalAll()方法实现线程之间的交互:
一个线程在临界区时,可能根据问题的需要,必须使用锁对象的await()方法使本线程等待,暂时让出CPU的使用权,并允许其他线程使用这个同步方法;
线程若退出临界区,应用signal()方法随机的选择一个线程解除其阻塞状态;
线程若退出临界区,执行notifyAll()方法通知所有由于等待该临界区的线程结束等待。
(2)在共享内存中的类方法前加synchronized修饰符;
synchronized关键字作用:
某个类内方法用synchronized修饰符后,该方法被称为同步线程;
只要某个线程正在访问同步方法,其他线程欲要访问同步方法就会被阻塞,直至线程从同步方法返回前唤醒被阻塞线程,其他线程方法可能进入同步方法;
第二部分:实验部分
实验1:测试程序1(5分)
l 在Elipse环境下调试教材651页程序14-7,结合程序运行结果理解程序;
l 掌握利用锁对象和条件对象实现的多线程同步技术。
实验代码如下:
package synch; import java.util.*;
import java.util.concurrent.locks.*; /**
* A bank with a number of bank accounts that uses locks for serializing access.
* @version 1.30 2004-08-01
* @author Cay Horstmann
*/
public class Bank
{
private final double[] accounts; //存储账户的数组
private Lock bankLock; //属性对象,两个与同步控制的标准类
private Condition sufficientFunds; //条件对象
//
/**
* Constructs the bank.
* @param n the number of accounts
* @param initialBalance the initial balance for each account
*/
public Bank(int n, double initialBalance) //Bank构造器,两个入口参数
{
accounts = new double[n];
Arrays.fill(accounts, initialBalance);
bankLock = new ReentrantLock(); //构建一个可以被用来保护临界区的可重入锁。
sufficientFunds = bankLock.newCondition(); //返回一个与该锁有关的条件对象
} /**
* Transfers money from one account to another.
* @param from the account to transfer from
* @param to the account to transfer to
* @param amount the amount to transfer
*/
public void transfer(int from, int to, double amount) throws InterruptedException //同行之间的转账操作
{
bankLock.lock(); //加锁操作
try
{
while (accounts[from] < amount) //当账户余额不足时
sufficientFunds.await(); //把该线程放在条件的等待集中,当前线程被阻塞,并且放弃了锁
System.out.print(Thread.currentThread());
accounts[from] -= amount;
System.out.printf(" %10.2f from %d to %d", amount, from, to);
accounts[to] += amount;
System.out.printf(" Total Balance: %10.2f%n", getTotalBalance());
sufficientFunds.signalAll(); //解除全部被阻塞的线程
}
finally
{
bankLock.unlock(); //释放这个锁
}
} /**
* Gets the sum of all account balances.
* @return the total balance
*/
public double getTotalBalance() //使用了公共资源
{
bankLock.lock(); //加锁操作
try
{
double sum = 0; for (double a : accounts)
sum += a; return sum;
}
finally
{
bankLock.unlock(); //释放该锁
}
} /**
* Gets the number of accounts in the bank.
* @return the number of accounts
*/
public int size()
{
return accounts.length;
}
}
package synch; /**
* This program shows how multiple threads can safely access a data structure.
* @version 1.31 2015-06-21
* @author Cay Horstmann
*/
public class SynchBankTest
{ //常量的定义
public static final int NACCOUNTS = 100;
public static final double INITIAL_BALANCE = 1000;
public static final double MAX_AMOUNT = 1000;
public static final int DELAY = 10; public static void main(String[] args)
{
Bank bank = new Bank(NACCOUNTS, INITIAL_BALANCE);
for (int i = 0; i < NACCOUNTS; i++)
{
int fromAccount = i;
Runnable r = () -> { //Runnable接口实现创建线程
try
{
while (true)
{
int toAccount = (int) (bank.size() * Math.random()); //随机函数产生
double amount = MAX_AMOUNT * Math.random(); //随机函数产生MAX_AMOUNT个随机数
bank.transfer(fromAccount, toAccount, amount); //调用transfer方法在同行之间进行转账
Thread.sleep((int) (DELAY * Math.random())); //随机睡眠时间DELAY
}
}
catch (InterruptedException e)
{
}
};
Thread t = new Thread(r); //创建一个线程
t.start(); //该线程开始工作
}
}
}
运行结果如下:

实验1:测试程序2(5分)
l 在Elipse环境下调试教材655页程序14-8,结合程序运行结果理解程序;
l 掌握synchronized在多线程同步中的应用。
实验代码如下:
package synch2; import java.util.*; /**
* A bank with a number of bank accounts that uses synchronization primitives.
* @version 1.30 2004-08-01
* @author Cay Horstmann
*/
public class Bank
{
private final double[] accounts; //常量数组的定义 /**
* Constructs the bank.
* @param n the number of accounts
* @param initialBalance the initial balance for each account
*/
public Bank(int n, double initialBalance) //Bank构造器
{
accounts = new double[n];
Arrays.fill(accounts, initialBalance);
} /**
* Transfers money from one account to another.
* @param from the account to transfer from
* @param to the account to transfer to
* @param amount the amount to transfer
*/
public synchronized void transfer(int from, int to, double amount) throws InterruptedException
{
while (accounts[from] < amount)
wait(); //调用wait()方法,使线程处于等待状态直至解除
System.out.print(Thread.currentThread());
accounts[from] -= amount;
System.out.printf(" %10.2f from %d to %d", amount, from, to);
accounts[to] += amount;
System.out.printf(" Total Balance: %10.2f%n", getTotalBalance());
notifyAll(); //唤醒等待使用该资源的其他线程
} /**
* Gets the sum of all account balances.
* @return the total balance
*/
public synchronized double getTotalBalance()
{
double sum = 0; for (double a : accounts)
sum += a; return sum;
} /**
* Gets the number of accounts in the bank.
* @return the number of accounts
*/
public int size() //size方法
{
return accounts.length;
}
}
package synch2; /**
* This program shows how multiple threads can safely access a data structure,
* using synchronized methods.
* @version 1.31 2015-06-21
* @author Cay Horstmann
*/
public class SynchBankTest2
{ //常量的定义
public static final int NACCOUNTS = 100;
public static final double INITIAL_BALANCE = 1000;
public static final double MAX_AMOUNT = 1000;
public static final int DELAY = 10; public static void main(String[] args)
{
Bank bank = new Bank(NACCOUNTS, INITIAL_BALANCE);
for (int i = 0; i < NACCOUNTS; i++)
{
int fromAccount = i;
Runnable r = () -> { //Runnable接口创建线程
try
{
while (true)
{
int toAccount = (int) (bank.size() * Math.random()); //随机函数
double amount = MAX_AMOUNT * Math.random(); //产生 1000个随机数
bank.transfer(fromAccount, toAccount, amount); //transfer方法在同行之间进行转账
Thread.sleep((int) (DELAY * Math.random())); //随机产生0-10毫秒之间的一个数,调用sleep方法睡眠。
}
}
catch (InterruptedException e)
{
}
};
Thread t = new Thread(r); //新建一个线程
t.start(); //调用start方法开启线程
}
}
}
运行结果如下:

实验1:测试程序3(5分)
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();
}
}
运行结果如下:

实验2:结对编程练习包含以下4部分(10分)
利用多线程及同步方法,编写一个程序模拟火车票售票系统,共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) 程序设计思路简述;
在主函数当中创建三个线程,写一个线程类,是实现Runnable接口的类,调用synchronized关键字实现线程的同步。
2) 符合编程规范的程序代码;
3) 程序运行功能界面截图;
实验代码如下:
class thread implements Runnable {
    int ticket = 1;
    boolean flag = true;
    @Override
    public void run() {
        while (flag) {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            synchronized (this) {
                if (ticket <= 10) {
                    System.out.println(Thread.currentThread().getName() + "窗口售:第" + ticket + "张票");
                    ticket++;
                }
                if (ticket > 10) {
                    flag = false;
                }
            }
        }
    }
}
public class Demo {
    public static void main(String[] args) {
        thread mythread = new thread();
        Thread ticket1 = new Thread(mythread);
        Thread ticket2 = new Thread(mythread);
        Thread ticket3 = new Thread(mythread);
        ticket1.start();
        ticket2.start();
        ticket3.start();
    }
}
运行结果如下:

实验总结:(5分)
本周学习了线程的知识,这次作业主要是关于同步线程的知识。上课通过老师的讲解代码以及运行结果的分析,对同步线程又了一定的理解,掌握了线程同步的两种方法。(1)引入ReentrantLock类;(2)在共享内存中的类方法前加synchronized修饰符;
synchronized关键字作用: 某个类内方法用synchronized修饰符后,该方法被称为同步线程; 只要某个线程正在访问同步方法,其他线程欲要访问同步方法就会被阻塞,直至线程从同步方法返回前唤醒被阻塞线程,其他线程方法可能进入同步方法.编程练习是对同步线程的应用。
201871010119-帖佼佼《面向对象程序设计(java)》第十七周学习总结的更多相关文章
- 201771010134杨其菊《面向对象程序设计java》第九周学习总结
		
第九周学习总结 第一部分:理论知识 异常.断言和调试.日志 1.捕获 ...
 - 201871010132-张潇潇《面向对象程序设计(java)》第一周学习总结
		
面向对象程序设计(Java) 博文正文开头 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cn ...
 - 扎西平措 201571030332《面向对象程序设计 Java 》第一周学习总结
		
<面向对象程序设计(java)>第一周学习总结 正文开头: 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 ...
 - 杨其菊201771010134《面向对象程序设计Java》第二周学习总结
		
第三章 Java基本程序设计结构 第一部分:(理论知识部分) 本章主要学习:基本内容:数据类型:变量:运算符:类型转换,字符串,输入输出,控制流程,大数值以及数组. 1.基本概念: 1)标识符:由字母 ...
 - 201871010124 王生涛《面向对象程序设计JAVA》第一周学习总结
		
项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://edu.cnblogs.com/campus/xbsf/ ...
 - 201871010115——马北《面向对象程序设计JAVA》第二周学习总结
		
项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p ...
 - 201777010217-金云馨《面向对象程序设计(Java)》第二周学习总结
		
项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p ...
 - 201871010132——张潇潇《面向对象程序设计JAVA》第二周学习总结
		
项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p ...
 - 201771010123汪慧和《面向对象程序设计Java》第二周学习总结
		
一.理论知识部分 1.标识符由字母.下划线.美元符号和数字组成, 且第一个符号不能为数字.标识符可用作: 类名.变量名.方法名.数组名.文件名等.第二部分:理论知识学习部分 2.关键字就是Java语言 ...
 - 马凯军201771010116《面向对象与程序设计Java》第九周学习总结
		
一.理论知识部分 异常.日志.断言和调试 1.异常:在程序的执行过程中所发生的异常事件,它中断指令的正常执行. 2.Java的异常处理机制可以控制程序从错误产生的位置转移到能够进行错误处理的位置. 3 ...
 
随机推荐
- 面向对象程序设计(Java) 第7周学习指导及要求
			
2019面向对象程序设计(Java)第7周学习指导及要求 (2019.10.11-2019.10.14) 学习目标 掌握四种访问权限修饰符的使用特点: 掌握Object类的用途及常用API: 掌握Ar ...
 - luoguP4151 [WC2011]最大XOR和路径
			
题意 这题有点神啊. 首先考虑注意这句话: 路径可以重复经过某些点或边,当一条边在路径中出现了多次时,其权值在计算 XOR 和时也要被计算相应多的次数 也就是说如果出现下面的情况: 我们可以通过异或上 ...
 - 前端Vue项目——购物车页面
			
一.加入购物车的两种策略 1.加入购物车接口 在 src/restful/api.js 中写入添加购物车接口: // 加入购物车的接口 export const shopCart = (params) ...
 - 修改gradle中央仓库,加快jar包下载速度
			
打开gradle项目的build.gradle文件 找到repositories,注释掉mavenCentral(),使用阿里云的仓库地址 repositories { //mavenCentral( ...
 - Unity Profiler 记录
			
版本 Unity 2018.4.6f1 空包 development build 魅蓝 note3 OPPO R9 VIVO x9 华为 P8 青春版 小米 8 SE iphone se Other ...
 - ajax.readyState和HTTP状态码的提示
			
ajax.readyState 0 -(未初始化)还没有调用send()方法 1 -(载入)已调用send()方法,正在发送请求 2 -(载入完成)send()方法执行完成,已经接收到全部响应内容 3 ...
 - Go Modules使用教程(3分钟学会)
			
前言 随着Go 1.13发布,GOPROXY默认值proxy.golang.org在中国大陆不能被访问. 七牛云顺势推出goproxy.cn,以利于中国开发者更好使用Go Modules,它是非盈利性 ...
 - 在net Core3.1上基于winform实现依赖注入实例
			
目录 在net Core3.1上基于winform实现依赖注入实例 1.背景 2.依赖注入 2.1依赖注入是什么? 2.1依赖注入的目的 2.2依赖注入带来的好处 2.2.1生命周期的控制 2.2.2 ...
 - linux中dd命令详解
			
本文转自:https://www.cnblogs.com/yuanqiangfei/p/9138625.html 一.dd命令的解释 dd:用指定大小的块拷贝一个文件,并在拷贝的同时进行指定的转换. ...
 - tensorflow之tf.shape()
			
tf.shape()这个方法就相当于numpy当中shape属性. 下面通过列子来了解: 具体而言,tf.shape是用来获取张量的维度(shape).