徐思 201771010132
一、理论知识部分:
程序是一段静态的代码,它是应用程序执行的蓝本。进程是程序的一次动态执行,它对应了从代码加载、执行至执行完毕的一个完整过程。操作系统为每个进程分配一段独立的内存空间和系统资源,包括:代码数据以及堆栈等资源。每一个进程的内部数据和状态都是完全独立的。多任务操作系统中,进程切换对CPU资源消耗较大。
多线程是进程执行过程中产生的多条执行线索。线程是比进程执行更小的单位。线程不能独立存在,必须存在于进程中,同一进程的各线程间共享进程空间的数据。每个线程有它自身的产生、存在和消亡的过程,是一个动态的概念。多线程意味着一个程序的多行语句可以看上去几乎在同一时间内同时运行。线程创建、销毁和切换的负荷远小于进程,又称为轻量级进程。
Java实现多线程有两种途径:创建Thread类的子类;在程序中定义实现Runnable接口的类。
用Thread类的子类创建线程:首先需从Thread类派生出一个子类,在该子类中重写run()方法。然后用创建该子类的对象Lefthand left=new Lefthand(); Righthand right=new Righthand();最后用start()方法启动线程 left.start(); right.start();
用Thread类的子类创建多线程的关键性操作:定义Thread类的子类并实现用户线程操作,即run()方法的实现。在适当的时候启动线程。由于Java只支持单重继承,用这种方法定义的类不可再继承其他父类。
用Runnable()接口实现线程:首先设计一个实现Runnable接口的类;然后在类中根据需要重写run方法;再创建该类对象,以此对象为参数建立Thread 类的对象;调用Thread类对象的start方法启动线程,将 CPU执行权转交到run方法。
Thread(Runnable r):创建一个新线程,它调用r的run(), r是一个实现了Runnable接口的类的实例。
线程两种创建方法比较:实现Runnable接口的优势:符合OO设计的思想;便于用extends继承其它类。采用继承Thread类方法的优点:代码简单。
线程的终止:当线程的run方法执行方法体中最后一条语句后,或者出现了在run方法中没有捕获的异常时,线程将终止,让出CPU使用权。调用interrupt()方法也可终止线程。 void interrupt() :向一个线程发送一个中断请求,同时把这个线程的“interrupted”状态置为true。若该线程处于 blocked 状 态,会抛出 InterruptedException。
测试线程是否被中断的方法:static boolean interrupted() :检测当前线程是否已被中断,并重置状态 “interrupted”值为false。 boolean isInterrupted() :检测当前线程是否已被中断 , 不改变状态 “interrupted”值 。
利用各线程的状态变换,可以控制各个线程轮流 使用CPU,体现多线程的并行性特征。
线程有如下7种状态:New (新建);Runnable (可运行);Running(运行) ;Blocked (被阻塞) ;Waiting (等待) ;Timed waiting (计时等待) ; Terminated (被终止)。
new(新建):线程对象刚刚创建,还没有启动,此时线程还处于不可运行状态。例如: Thread thread=new Thread(r); 此时线程thread处于新建状态,有了相应的内存空间以及其它资源。
runnable(可运行状态):此时线程已经启动,处于线程的run()方法之中。此时的线程可能运行,也可能不运行,只要 CPU一空闲,马上就会运行。调用线程的start()方法可使线程处于“可运行”状态。例如: thread.start();
blocked (被阻塞):一个正在执行的线程因特殊原因,被暂停执行,进入阻塞状态。阻塞时线程不能进入队列排队,必须等到引起阻塞的原因消除,才可重新进入排队队列。引起阻塞的原因很多,不同原因要用不同的方法解除。sleep(),wait()是两个常用引起线程阻塞的方法。
线程阻塞的三种情况:等待阻塞:通过调用线程的wait()方法,让线程等待某工作的完成。同步阻塞:线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻 塞状态。 其他阻塞:通过调用线程的sleep()或join() 或发出了I/O请求时,线程会进入到阻塞状态。当 sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
Terminated (被终止) :线程被终止的原因有二:一是run()方法中最后一个语句执行完毕而自 然死亡。二是因为一个没有捕获的异常终止了run方法而意外死亡。可以调用线程的 stop 方法杀死一个线程(thread.stop();),但是,stop方法已过时,不要在自己的代码中调用它。
线程的挂起和恢复: suspend() 和 resume() 方法:两个方法可配套使用,suspend()使得线程进入阻塞状态,并且不会自动恢复,必须其对应的 resume()被调用, 才能使得线程重新进入可执行状态。但这种方法很容易引起线程死锁问题,已不推荐使用。
其他判断和影响线程状态的方法:join():等待指定线程的终止。 join(long millis):经过指定时间等待终止指定的线程。 isAlive():测试当前线程是否在活动。 yield():让当前线程由“运行状态”进入到“就绪状态” ,从而让其它具有相同优先级的等待线程获取执行权。
Java 的线程调度采用优先级策略:优先级高的先执行,优先级低的后执行;多线程系统会自动为每个线程分配一个优先级,缺省时,继承其父类的优先级; 任务紧急的线程,其优先级较高; 同优先级的线程按“先进先出”的队列原则。
Thread类有三个与线程优先级有关的静态量: MAX_PRIORITY:最大优先权,值为10; MIN_PRIORITY:最小优先权,值为1; NORM _PRIORITY:默认优先权,值为5。
调用setPriority(int a)重置当前线程的优先级,a取值可以是前述的三个静态量。调用getPriority()获得当前线程优先级。
下面几种情况下,当前运行线程会放弃CPU:线程调用了yield() 或sleep() 方法;抢先式系统下,有高优先级的线程参与调度;由于当前线程进行I/O访问、外存读写、等待用 户输入等操作导致线程阻塞;或者是为等候一个条件变量,以及线程调用wait() 方法。
守护线程的惟一用途是为其他线程提供服务。例如计时线程。在一个线程启动之前,调用setDaemon方法可将线程转换为守护线程。例如:setDaemon(true);
多线程并发执行中的问题:多个线程相对执行的顺序是不确定的。线程执行顺序的不确定性会产生执行结果的不确定性。在多线程对共享数据操作时常常会产生这种不确定性
多线程并发运行不确定性问题解决方案:引入线程同步机制,使得另一线程要使用该方法,就只能等待。
在Java中解决多线程同步问题的方法有两种:J ava SE 5.0中引入ReentrantLock类。 在共享内存的类方法前加synchronized修饰符。
有关锁对象和条件对象的关键要点:锁用来保护代码片段,保证任何时刻只能有一个线程执行被保护的代码。锁管理试图进入被保护代码段的线程。锁可拥有一个或多个相关条件对象。每个条件对象管理那些已经进入被保护的代码 段但还不能运行的线程。
synchronized关键字作用: 某个类内方法用synchronized 修饰后,该方法被称为同步方法;只要某个线程正在访问同步方法,其他线程欲要访问同步方法就被阻塞,直至线程从同 步方法返回前唤醒被阻塞线程,其他线程方可能进入同步方法。
在同步方法中使用wait()、notify 和notifyAll()方法:一个线程在使用的同步方法中时,可能根据问题的需要,必须使用wait()方法使本线程等待,暂时让出CPU的使用权,并允许其它线程使用这个同步方法。线程如果用完同步方法,应当执行notifyAll()方 法通知所有由于使用这个同步方法而处于等待的线程结束等待。
二、实验部分:
1、实验目的与要求
(1) 掌握线程同步的概念及实现技术;
(2) 线程综合编程练习
2、实验内容和步骤
实验1:测试程序并进行代码注释。
测试程序1:
l 在Elipse环境下调试教材651页程序14-7,结合程序运行结果理解程序;
l 掌握利用锁对象和条件对象实现的多线程同步技术。
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 = () -> {try {while (true) {int toAccount = (int) (bank.size() * Math.random());double amount = MAX_AMOUNT * Math.random();bank.transfer(fromAccount, toAccount, amount);Thread.sleep((int) (DELAY * Math.random()));// 在指定的毫秒数内让当前正在执行的线程休眠 }} catch (InterruptedException e) {}};Thread t = new Thread(r);// 分配新的 Thread 对象t.start();// 开始线程 }} }
SynchBankTest
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) {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;} }
Bank
测试程序2:
l 在Elipse环境下调试教材655页程序14-8,结合程序运行结果理解程序;
l 掌握synchronized在多线程同步中的应用。
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 = () -> {try {while (true) {int toAccount = (int) (bank.size() * Math.random());double amount = MAX_AMOUNT * Math.random();bank.transfer(fromAccount, toAccount, amount);Thread.sleep((int) (DELAY * Math.random()));// 在指定的毫秒数内让当前正在执行的线程休眠 }} catch (InterruptedException e) {}};Thread t = new Thread(r);// 分配新的 Thread 对象t.start();// 使线程开始执行 }} }
SynchBankTest2
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) {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();// 添加一个线程到等待集中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() {return accounts.length;} }
Bank
测试程序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(); } } |
运行结果:
class Cbank {private static int s = 2000;public synchronized 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 编程练习
利用多线程及同步方法,编写一个程序模拟火车票售票系统,共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张票
public class Demo {public static void main(String[] args) {Mythread mythread = new Mythread();Thread t1 = new Thread(mythread);Thread t2 = new Thread(mythread);Thread t3 = new Thread(mythread);t1.start();t2.start();t3.start();} }class Mythread implements Runnable {int t = 1;boolean flag = true;@Overridepublic void run() {// TODO Auto-generated method stubwhile (flag) {try {Thread.sleep(500);} catch (Exception e) {// TODO: handle exception e.printStackTrace();}synchronized (this) {if (t <= 10) {System.out.println(Thread.currentThread().getName() + "窗口售:第" + t + "张票");t++;}if (t > 10) {flag = false;}}}} }
三、实验总结:
这次实验比较简单,编程需要多加练习,知识点也需好好复习,为期末做准备。
转载于:https://www.cnblogs.com/sisi-713/p/10150960.html
徐思 201771010132相关推荐
- 第三周java实验报告
实验三 Java基本程序设计(2) 实验时间 2018-9-13 第一部分:理论知识回顾 第一章 再次了解了java"白皮书"的关键术语,java的常见术语,对于大多数&q ...
- MPB:林科院袁志林组-原生质体法制备根系腐生型共生菌(伞菌目)单核化菌丝...
为进一步提高<微生物组实验手册>稿件质量,本项目新增大众评审环节.文章在通过同行评审后,采用公众号推送方式分享全文,任何人均可在线提交修改意见.公众号格式显示略有问题,建议电脑端点击文末阅 ...
- 第十六届全国大学智能车竞赛东北赛区成绩与奖项
正式文档将会在竞赛网站公布: smartcar.cdstm.cn §01 成绩与奖项 一.基础四轮组 [表1-1 基础四轮成绩与奖项] 序号 学校 队伍 学生1 学生2 学生3 指导教师1 指导教 ...
- 第十五届全国大学生智能车竞赛安徽赛区比赛报名信息
➤ 01普通四轮组 序号 学校名称 队伍名称 带队教师 学生1 学生2 学生3 1 安徽财经大学 追光者 现场确定 李开峰 马天祺 叶凡 2 安徽财经大学 所有题全队 现场确定 张波 孙京 王佳慧 3 ...
- 准确率不变 损失率下降_最新斯诺克排名奥沙利文排在第二,丁俊晖排第十,第一保持不变...
随着2020-2021赛季冠军联赛决赛落下战幕,世界斯诺克最新的排名也有所变动.目前英格兰选手贾德·特鲁姆普以1699500英镑依然占据第一位.而在冠军联赛决赛以3-1的比分击败贾德·特鲁姆普的凯伦· ...
- 《那些年啊,那些事——一个程序员的奋斗史》——42
深圳最高的山是哪座?梧桐山!梧桐山这名字如何由来的?据说以前一些村民爬到山顶,看到海另一端的香港异常繁华,和当时的深圳比起来简直是天上和地下,所以不由地发出感慨:"吾同(不同),吾同(不同) ...
- 大疆无人机高程不准_大疆消费级无人机快速倾斜摄影测量实践
摘要:分别用 RTK两种测量模式测定像控点,用大疆消费级无人机 Phantom4PRO 开展倾斜摄影测量,最后进行成果检验.结果表明:RTK 电台模式(不做坐标校正,精度低).RTK-CORS 网络模 ...
- 听到表扬的飞鸽传书2011
听到表扬的飞鸽传书2011 今天的听到表扬的飞鸽传书2011(http://blog.csdn.net/i_like_cpp/),这没什么,说她是少有的爱帮助人的独生子女,风景如画的东水关城墙昨天,我 ...
- 产业区块链:新基建中的底层技术基座,各行业资深人士应积极参与建设
记者 | 邓晓娟 出品 | CSDN(ID:CSDNnews) 4月20日,国家发改委召开例行在线新闻发布会,国家发改委创新和高技术发展司司长伍浩回应外界对新基建的热议.他表示,关于新型基础设施的概念 ...
- 2019南昌市计算机教师招聘,南昌经济技术开发区2019年招聘教师拟聘用人员名单...
根据江西省教育厅.江西省人力资源和社会保障厅<关于做好2019年全省中小学教师招聘工作的通知>(赣教师字[2019]5号)和<江西省2019年中小学教师招聘公告>的文件精神,及 ...
最新文章
- 【AI】CelebA数据介绍、下载及说明
- android studio使用问题——instant run
- 我与技术------2012程序之路
- 谷歌新模型突破BERT局限:NLP版「芝麻街」新成员Big Bird长这样
- 商业级全局负载均衡器 zeus.ZXTM 实施方案
- NumPy 数组对象
- ML之xgboost:解读用法之xgboost库的core.py文件中的get_score(importance_type=self.importance_type)方法
- Burpsuite中protobuf数据流的解析 - Vincent
- 构建属于你自己的dapr服务发现
- 104. 二叉树的最大深度 golang
- HDU 4635(强连通分量分解
- 楼主考南师计算机学硕,【图片】2019南师大新传学硕考研经验贴【南京师范大学研究生吧】_百度贴吧...
- Idea利用maven打包spring boot项目
- 软件工程(2019)第二次作业
- 谈谈JS的全局变量跟局部变量
- Flutter 页面弹出毛玻璃浮层
- 数据可视化|用散点图进行数据分析
- Docker码头工人之将爬虫放入docker运行
- HTML模拟电池页面,Html 电池图标
- 毕业设计c语言课程设计,毕业设计—c语言—课程设计.doc