• Java必做实验4线程应用


    (1). 运行以下三个程序(要求每个程序运行10次),并对输出结果给出分析。在报告中附上程序截图和详细的文字说明。(15分)

    程序1:

    1. package first;
    2. //The Task for printing a character a specified number of times
    3. class PrintChar implements Runnable{
    4. private char charToPrint;//The character to print
    5. private int times;//The number of times to repeat
    6. public PrintChar(char c,int t){
    7. charToPrint=c;
    8. times=t;
    9. }
    10. @Override/*Override the run()method to tell the system
    11. *what task to perform
    12. */
    13. public void run(){
    14. for(int i=0;i
    15. System.out.print(charToPrint);
    16. }
    17. System.out.println();
    18. }
    19. }
    20. class PrintNum implements Runnable{
    21. private int lastNum;
    22. //Construct a task for printing 1,2,...,n
    23. public PrintNum(int n){
    24. lastNum=n;
    25. }
    26. //Tell the Thread how to run
    27. public void run(){
    28. for(int i=1;i<=lastNum;i++)
    29. System.out.print(" "+i);
    30. System.out.println();
    31. }
    32. }
    33. public class ExecutorDemo {
    34. public static void main(String args[]){
    35. //Creat tasks
    36. Runnable printA=new PrintChar('a',100);
    37. Runnable printB=new PrintChar('b',100);
    38. Runnable print100=new PrintNum(100);
    39. //Creat threads
    40. Thread thread1=new Thread(printA);
    41. Thread thread2=new Thread(printB);
    42. Thread thread100=new Thread(print100);
    43. //Start threads
    44. thread1.start();
    45. thread2.start();
    46. thread100.start();
    47. }
    48. }

    该程序是线程异步功能是的输出100个a,100个b和100个数字(1~100)

    程序2:

    该程序与上一题不同的是运用了线程池,用newFixedThreadPool创建了一个线程数为3的线程池,然后将和第一个程序相同的三个线程任务放进线程池,但运行时仍然是线程异步。

    代码如下:

    1. package first_2;
    2. import java.util.concurrent.ExecutorService;
    3. import java.util.concurrent.Executors;
    4. //The Task for printing a character a specified number of times
    5. class PrintChar implements Runnable{
    6. private char charToPrint;//The character to print
    7. private int times;//The number of times to repeat
    8. public PrintChar(char c,int t){
    9. charToPrint=c;
    10. times=t;
    11. }
    12. @Override/*Override the run()method to tell the system
    13. *what task to perform
    14. */
    15. public void run(){
    16. for(int i=0;i
    17. System.out.print(charToPrint);
    18. }
    19. System.out.println();
    20. }
    21. }
    22. class PrintNum implements Runnable{
    23. private int lastNum;
    24. //Construct a task for printing 1,2,...,n
    25. public PrintNum(int n){
    26. lastNum=n;
    27. }
    28. //Tell the Thread how to run
    29. public void run(){
    30. for(int i=1;i<=lastNum;i++)
    31. System.out.print(" "+i);
    32. System.out.println();
    33. }
    34. }
    35. public class ExecutorDemo {
    36. public static void main(String args[]){
    37. //Creat a fixed thread pool with maxinum three threads
    38. ExecutorService executor= Executors.newFixedThreadPool(3);
    39. //Submit runnable tasks to the executor
    40. executor.execute(new PrintChar('a',100));
    41. executor.execute(new PrintChar('b',100));
    42. executor.execute(new PrintNum(100));
    43. //Shut down the executor
    44. executor.shutdown();
    45. }
    46. }

    可见仍无规律可循,说明线程池的多线程是线程异步的。

    1. package first_3;
    2. import java.util.concurrent.*;
    3. public class AccountWithoutDSync {
    4. private static Account account = new Account();
    5. public static void main(String args[]) {
    6. ExecutorService executor = Executors.newCachedThreadPool();
    7. //Creat and launch 100 threads
    8. for (int i = 0; i < 100; i++) {
    9. executor.execute(new AddAPennyTask());
    10. }
    11. executor.shutdown();
    12. //Wait until all tasks are finished
    13. while (!executor.isTerminated()) {
    14. }
    15. System.out.println("What is balance? " + account.getBalance());
    16. }
    17. //A thread for adding a penny to the account
    18. private static class AddAPennyTask implements Runnable {
    19. public void run() {
    20. account.deposit(1);
    21. }
    22. }
    23. //An inner class for account
    24. private static class Account {
    25. private int balance = 0;
    26. public int getBalance() {
    27. return balance;
    28. }
    29. public void deposit(int amount) {
    30. int newBalance = balance + amount;
    31. //This delay is deliberately added to magnify the
    32. //data-corruption problem and make it easy to see.
    33. try {
    34. Thread.sleep(5);
    35. } catch (InterruptedException ex) {
    36. }
    37. balance = newBalance;
    38. }
    39. }
    40. }

    程序3: 

    1. package first_3;
    2. import java.util.concurrent.*;
    3. public class AccountWithoutDSync {
    4. private static Account account = new Account();
    5. public static void main(String args[]) {
    6. ExecutorService executor = Executors.newCachedThreadPool();
    7. //Creat and launch 100 threads
    8. for (int i = 0; i < 100; i++) {
    9. executor.execute(new AddAPennyTask());
    10. }
    11. executor.shutdown();
    12. //Wait until all tasks are finished
    13. while (!executor.isTerminated()) {
    14. }
    15. System.out.println("What is balance? " + account.getBalance());
    16. }
    17. //A thread for adding a penny to the account
    18. private static class AddAPennyTask implements Runnable {
    19. public void run() {
    20. account.deposit(1);
    21. }
    22. }
    23. //An inner class for account
    24. private static class Account {
    25. private int balance = 0;
    26. public int getBalance() {
    27. return balance;
    28. }
    29. public void deposit(int amount) {
    30. int newBalance = balance + amount;
    31. //This delay is deliberately added to magnify the
    32. //data-corruption problem and make it easy to see.
    33. try {
    34. Thread.sleep(5);
    35. } catch (InterruptedException ex) {
    36. }
    37. balance = newBalance;
    38. }
    39. }
    40. }

    (2). 编写Java应用程序实现如下功能:第一个线程输出数字1,2,..,12,第二个线程输出英文单词数字和月份One January, Two February, …, Twelve December,输出的顺序和格式为1OneJanuary2TwoFebruary...12TwelveDecember,即每1个数字紧跟着2个英文单词的方式。要求线程间实现通信。要求采用实现Runnable接口和Thread类的构造方法的方式创建线程,而不是通过Thread类的子类的方式。在报告中附上程序截图、运行结果截图和详细的文字说明。(15分)

    这题最主要的还是线程之间的通信,在每个线程

    输出相应的数字或字符后,在下一个输出前,都要判断是否要wait,才能保证相互的连续性

    源代码如下:

    首先是实现两者通信的类(单独开了一个包):

    其中定义了两个线程的进度timeOf...;然后先定义了一个String类型的数组month来使后面输出方便,再就是分别定义了synchronized 下的printNumber和printChatrs方法来使两线程同时进行两着主语句相差不大,printChars下定义了一个index来记录访问month的下标,注意一下两线程的输出顺序(再if里面注意判断)。

    1. package second;
    2. public class Connect {
    3. int timesOfInt = 1;
    4. int timesOfString = 1;
    5. String []month = {"One January", "Two February", "Three March", "Four April", "Five May",
    6. "Six June", "Seven July", "Eight August", "Nine September", "Ten October", "Eleven November", "Twelve December"
    7. };//先定义一下月份,方便输出
    8. synchronized void printNumber() {//线程1实现的输出1到12
    9. for (timesOfInt = 1; timesOfInt <= 12; timesOfInt++) {
    10. if (timesOfInt > timesOfString) //对应的字母未输出
    11. {
    12. try {wait();}
    13. catch (InterruptedException ex) {}
    14. }
    15. System.out.print(timesOfInt);
    16. notify();//输出后唤醒另一个线程
    17. }
    18. }
    19. synchronized void printChars() {//线程2输出One January到Twelve December
    20. int index = 0;//记录month的下标
    21. for (timesOfString = 1; timesOfString <= 12; timesOfString++) {
    22. if (timesOfInt <= timesOfString) {//相应数字未输出
    23. try {wait();}
    24. catch (InterruptedException ex) {}
    25. }
    26. System.out.print(month[index++]+" ");//加个空格输出美观点
    27. notify();//唤醒另一个线程
    28. }
    29. }
    30. }

    然后在主运行的类下定义了两个方法printInt和printString均继承了Runnable接口,通过它们来调用非静态Connect中的方法,main类大体就只是调用:

    1. package second;
    2. class printInt implements Runnable{
    3. Connect connect;//创建了connect类实例为了调用非static方法
    4. printInt (Connect connect1){connect=connect1;}
    5. public void run(){connect.printNumber();}//实现Ruunable接口
    6. }
    7. class printString implements Runnable{
    8. Connect connect;//创建了connect类实例为了调用非static方法
    9. printString(Connect connect1){connect=connect1;}
    10. public void run(){connect.printChars();}//实现Ruunable接口
    11. }
    12. public class second{ public static void main(String args[]){
    13. Connect connect=new Connect();//同一connect创建线程确保通信
    14. Thread threadA=new Thread(new printInt(connect));//Thread方法实现接口
    15. Thread threadB=new Thread(new printString(connect));
    16. threadA.start();
    17. threadB.start();
    18. }
    19. }

    (3). 编写Java应用程序实现如下功能:创建工作线程,模拟银行现金账户取款操作。多个线程同时执行取款操作时,如果不使用同步处理,会造成账户余额混乱,要求使用syncrhonized关键字同步代码块,以保证多个线程同时执行取款操作时,银行现金账户取款的有效和一致。要求采用实现Runnable接口和Thread类的构造方法的方式创建线程,而不是通过Thread类的子类的方式。在报告中附上程序截图、运行结果截图和详细的文字说明。(25分)

    这道题很明显用syncrhonized的目的是,存钱时使得这次存款对应的输出余额相对应,不要让同时存的另一个数额也加进这次的余额计算中,所以采用syncrhonized关键字实现

    源代码如下:

    1. package third;
    2. import java.util.*;
    3. class Account implements Runnable{
    4. private double account;//账户总额
    5. private String name;//账户名
    6. public double outAccount;//取款
    7. Account(double money,String s){
    8. account=money;
    9. name=s;
    10. }
    11. void setOutAccount(){
    12. System.out.print("请输入要取款的金额:");
    13. Scanner scanner=new Scanner(System.in);
    14. outAccount=scanner.nextDouble();
    15. }
    16. public synchronized void run(){
    17. setOutAccount();//outAccount记录这次要取的数目
    18. if(account
    19. System.out.println("余额不够哦qwq");
    20. }
    21. else{
    22. account-=outAccount;
    23. System.out.print("取款的金额为:");
    24. System.out.println(outAccount);
    25. System.out.println(name+"账户下的余额为:"+account);
    26. }
    27. }
    28. }
    29. public class third {
    30. public static void main(String args[]){
    31. Account account=new Account(10000,"彭于晏");//有参构造创建Account类实例account
    32. System.out.print("请输入你要取款的次数:");
    33. Scanner scanner=new Scanner(System.in);
    34. int time=scanner.nextInt();
    35. for(int i=0;i//取款time次
    36. new Thread(account).start();
    37. }
    38. }

    注意删去Account下的run的synchronized也执行一次,发现第二次要求先输入所有取款金额而不删时不用。

    (4). 有一座东西向的桥,只能容纳一个人,桥的东边有20个人(记为E1,E2,…,E20)和桥的西边有20个人(记为W1,W2,…,W20),编写Java应用程序让这些人到达对岸,每个人用一个线程表示,桥为共享资源,在过桥的过程中输出谁正在过桥(不同人之间用逗号隔开)。运行10次,分别统计东边和西边的20人先到达对岸的次数。要求采用实现Runnable接口和Thread类的构造方法的方式创建线程,而不是通过Thread类的子类的方式。在报告中附上程序截图、运行结果截图和详细的文字说明。(25分)

    这题和第一题2有点类似的样子,所以直接套过来用了。

    源代码:

    东边的人定义,变量有名字name第几个人num(用num+1表示),方法setEast实现了对East类的初始化,随后就是对run的实现.

    西边的人的定义与东边基本一样,名字啥的修改一下就好了。

    1. package four;
    2. class East implements Runnable{
    3. private String name;//过桥人的名字
    4. private int num;//记录第num+1个人过桥(因为num当输出了)
    5. public void setEast(int num){//初始化我搞这了
    6. String s=Integer.toString(num);
    7. name="E"+s;
    8. this.num=num;
    9. }
    10. public void run(){//实现Runnable
    11. System.out.println(name+"正在过桥......");//输出过桥者的信息
    12. if(num==19)
    13. System.out.println("东边的人全部过桥啦!");//最后一人过桥则输出提
    14. }
    15. }
    16. class West implements Runnable{//与East类似的定义
    17. private String name;
    18. private int num;
    19. public void setWest(int num){//过桥者
    20. String s=Integer.toString(num);
    21. name="W"+s;
    22. this.num=num;
    23. }
    24. public void run(){
    25. System.out.println(name+"正在过桥......");//输出过桥者的信息
    26. if(num==19)//最后一人过桥则输出提示
    27. System.out.println("西边的人全部过桥啦!");
    28. }
    29. }
    30. public class Bridge {
    31. public static void main(String []args){
    32. for(int i=0;i<10;i++){
    33. int count=0;
    34. East []east=new East[20];
    35. West []west=new West[20];//定义桥的东西边各20个人
    36. Thread []threadWest=new Thread[20];
    37. Thread []threadEest=new Thread[20];//定义两边的线程
    38. for(int j=0;j<20;j++){
    39. east[j]=new East();
    40. east[j].setEast(j);
    41. threadEest[j]=new Thread();
    42. threadEest[j]=new Thread(east[j]);
    43. west[j]=new West();
    44. west[j].setWest(j);
    45. threadWest[j]=new Thread();
    46. threadWest[j]=new Thread(west[j]);//初始化
    47. }
    48. for(int j=0;j<20;j++){
    49. threadWest[j].start();
    50. threadEest[j].start();//开始
    51. }
    52. System.out.println("第"+(i+1)+"一波结束啦!");
    53. System.out.println("******分割******");
    54. }
    55. }
    56. }

    main主要实现了10次循环计数,以及对20个类和线程的初始化,然后就是计算东西

    先到达对岸的次数(太菜了只会看着答案人工计算)qwq。

  • 相关阅读:
    【汽车电子】万字详解汽车标定与XCP协议
    PCL——Filter
    HTML+CSS简单的网页制作期末作业 关于我的家乡——四川文化网页介绍 DW大学生网页作业制作设计 Dreamweaver简单网页成品
    C++入门教程(二、基本数据类型)
    C# 使用Newtonsoft.Json解析嵌套json
    持续集成交付CICD:安装Gitlab Runner(从节点)
    day03-2无异常退出
    跟上时代步伐的慢直播神器MZB01发布
    哪个电脑录屏软件好用又免费?十大好用的免费录屏软件排行
    【ChatGLM2-6B】小白入门及Docker下部署
  • 原文地址:https://blog.csdn.net/weixin_62431082/article/details/127990170