实验1 模拟抽奖
一、实验目的
了解多线程程序的设计思路
二、实验内容
有一个抽奖池,该抽奖池中存放了奖励的金额,该抽奖池用一个数组int[] arr = {10,5,20,50,100,200,500,800,2,80,300};创建两个抽奖箱(线程)设置线程名称分别为“抽奖箱1”,“抽奖箱2”,随机从arr数组中获取奖项元素并打印在控制台上
三、程序代码
1. public class ChouJiang { 2. public static void main(String[] args) { 3. Chou c = new Chou(); 4. Thread t1 = new Thread(c,"抽奖箱1");//创建线程对象t1,命名为“抽奖箱1” 5. Thread t2 = new Thread(c,"抽奖箱2");//创建线程对象t2,命名为“抽奖箱2” 6. t1.start(); 7. t2.start(); 8. } 9. } 10. class Chou implements Runnable { 11. int[] arr = { 10, 5, 20, 50, 100, 200, 500, 800, 2, 80, 300 }; 12. int num = arr.length; 13. boolean[] flag = new boolean[arr.length]; 14. public void run() { 15. while (true) { 16. synchronized (this) {//设计一个同步锁 17. if (num > 0) { 18. int index = (int)(Math.random()*arr.length);//产生数组的随机索引值 19. int get = arr[index]; 20. // 代表这张抽奖券抽过了 21. if (flag[index] != true) { 22. flag[index] = true; 23. System.out.println(Thread.currentThread().getName() 24. + " 又产生了一个" + get + "元大奖"); 25. num--; 26. } 27. } 28. } 29. } 30. } 31. }
四、实验指导
1、两个抽奖箱线程实现从抽奖池数组中抽取幸运数字
2、了解flag数组的含义,与抽奖池数组一一对应,判断该奖项是否抽出。
实验2 模拟订票
一、实验目的
掌握多线程程序的编写和线程同步的解决
二、实验内容
某电影院目前正在上映贺岁大片,共有100张票,而它有3个售票窗口售票,请设计一个程序模拟该电影院售票。
两种方式实现
继承Thread类
实现Runnable接口
三、程序代码
1. public class BuyTicket { 2. public static void main(String[] args) {//主函数 3. SaleWindowThread w1 = new SaleWindowThread(); 4. Thread t1 = new Thread(w1, "第一个售票窗口");//模拟三个售票窗口 5. Thread t2 = new Thread(w1, "第二个售票窗口"); 6. Thread t3 = new Thread(w1, "第三个售票窗口"); 7. t1.start(); //启动第一个售票窗口,开始售票 8. t2.start(); //启动第二个售票窗口,开始售票 9. t3.start(); //启动第三个售票窗口,开始售票 10. } 11. } 12. class SaleWindowThread implements Runnable { //实现Runnable接口 13. private static int total_count = 100; //电影票总数 14. @Override 15. public void run() { //重写run()方法 16. while (true) { 17. if (total_count > 0) { 18. synchronized(this){ 19. if (total_count > 0){ 20. System.out.println(Thread.currentThread().getName() + "售出第" + (100 - total_count + 1) + "张票。还剩"+ (total_count - 1) + "张"); 21. //记录售出票和剩余票数 22. total_count--; 23. } 24. } 25. } 26. else { 27. break; 28. } 29. } 30. } 31. }
四、实验指导
1、如果每次卖票延迟100毫秒,观察卖票信息是否正确
2、利用synchronized方法或代码块将共享资源封装,解决线程安全问题
实验3、打字练习
一、实验目的
掌握多线程和Timer类的使用
二、实验内容
通过GUI界面完成打字练习的功能
三、程序代码
1. import java.awt.Color; 2. import java.awt.FlowLayout; 3. import java.awt.Font; 4. import java.awt.event.ActionEvent; 5. import java.awt.event.ActionListener; 6. 7. import javax.swing.JFrame; 8. import javax.swing.JLabel; 9. import javax.swing.JTextField; 10. 11. public class Writer { 12. public static void main(String args[]) { 13. WindowTyped win=new WindowTyped(); 14. win.setTitle("打字练习"); 15. win.setSleepTime(3000); 16. } 17. } 18. class WindowTyped extends JFrame implements ActionListener,Runnable { 19. JTextField inputLetter; 20. Thread giveLetter; //负责给出字母 21. JLabel showLetter,showScore; 22. int sleepTime,score; 23. Color c; 24. WindowTyped() { 25. setLayout(new FlowLayout()); 26. giveLetter=new Thread(this); 27. inputLetter=new JTextField(6); 28. showLetter =new JLabel(" ",JLabel.CENTER); 29. showScore = new JLabel("分数:"); 30. showLetter.setFont(new Font("Arial",Font.BOLD,22)); 31. add(new JLabel("显示字母:")); 32. add(showLetter); 33. add(new JLabel("输入所显示的字母(回车)")); 34. add(inputLetter); 35. add(showScore); 36. inputLetter.addActionListener(this); 37. setBounds(100,100,400,280); 38. setVisible(true); 39. setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 40. giveLetter.start(); //在AWT-Windows线程中启动giveLetter线程 41. } 42. public void run() { 43. char c ='a'; 44. while(true) { 45. showLetter.setText(""+c+" "); 46. validate(); 47. c = (char)(c+1); 48. if(c>'z') c = 'a'; 49. try{ Thread.sleep(sleepTime); 50. } 51. catch(InterruptedException e){} 52. } 53. } 54. public void setSleepTime(int n){ 55. sleepTime = n; 56. } 57. public void actionPerformed(ActionEvent e) { 58. String s = showLetter.getText().trim(); 59. String letter = inputLetter.getText().trim(); 60. if(s.equals(letter)) { 61. score++; 62. showScore.setText("得分"+score); 63. inputLetter.setText(null); 64. validate(); 65. giveLetter.interrupt(); //吵醒休眠的线程,以便加快出字母的速度 66. } 67. } 68. }
四、实验指导
1、能够随机生成字符信息,对用户的操作有时间限制
2、有统计分数功能
实验4 月亮围绕地球
一、实验目的
学习使用Timer类创建线程
二、实验内容
编写一个应用程序,模拟月亮围绕地球
三、程序代码
1. import java.awt.Dimension; 2. import java.awt.FlowLayout; 3. import java.awt.event.ActionEvent; 4. import java.awt.event.ActionListener; 5. 6. import javax.swing.ImageIcon; 7. import javax.swing.JFrame; 8. import javax.swing.JLabel; 9. import javax.swing.SwingConstants; 10. import javax.swing.Timer; 11. 12. public class MainClass { 13. public static void main(String args[]) { 14. Sky sky= new Sky(); 15. JFrame frame = new JFrame(); 16. frame.add(sky); 17. frame.setSize(500,500); 18. frame.setVisible(true); 19. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 20. frame.getContentPane().setBackground(java.awt.Color.white); 21. }} 22. class Earth extends JLabel implements ActionListener { 23. JLabel moon; //显示月亮之外观 24. Timer timer; 25. double pointX[]=new double[360], 26. pointY[]=new double[360]; 27. int w=200,h=200,i=0; 28. Earth() { 29. setLayout(new FlowLayout()); 30. setPreferredSize(new Dimension(w,h)); 31. timer=new Timer(20,this);//创建timer,振铃间隔是20毫秒当前Earth对象为其监视器 32. setIcon(new ImageIcon("E:\\Java程序设计\\实验报告集合\\实验九\\earth.jpg")); 33. setHorizontalAlignment(SwingConstants.CENTER); 34. moon=new JLabel(new ImageIcon("E:\\Java程序设计\\实验报告集合\\实验九\\moon.jpg"),SwingConstants.CENTER); 35. add(moon); 36. moon.setPreferredSize(new Dimension(60,60)); 37. pointX[0]=0; 38. pointY[0]=h/2; 39. double angle=1*Math.PI/180; //刻度为1度 40. for(int i=0;i<359;i++) { //计算出数组中各个元素的值 41. pointX[i+1]=pointX[i]*Math.cos(angle)-Math.sin(angle)*pointY[i]; 42. pointY[i+1]=pointY[i]*Math.cos(angle)+pointX[i]*Math.sin(angle); 43. } 44. for(int i=0;i<360;i++) { 45. pointX[i]=0.8*pointX[i]+w/2; //坐标缩放、平移 46. pointY[i]=0.8*pointY[i]+h/2; 47. } 48. timer.start(); 49. } 50. public void actionPerformed(ActionEvent e) { 51. i=(i+1)%360; 52. moon.setLocation((int)pointX[i]-30,(int)pointY[i]-30); 53. } 54. } 55. class Sky extends JLabel implements ActionListener { 56. Earth earth; 57. Timer timer; 58. double pointX[]=new double[360], 59. pointY[]=new double[360]; 60. int w=400,h=400,i=0; 61. Sky() { 62. setLayout(new FlowLayout()); 63. timer= new Timer(100,this);//创建timer,振铃间隔是100毫秒当前Sky对象为其监视器 64. setPreferredSize(new Dimension(w,h)); 65. earth = new Earth(); 66. add(earth); 67. earth.setPreferredSize(new Dimension(200,200)); 68. pointX[0]=0; 69. pointY[0]=h/2; 70. double angle=1*Math.PI/180; //刻度为1度 71. for(int i=0;i<359;i++) { //计算出数组中各个元素的值 72. pointX[i+1]=pointX[i]*Math.cos(angle)-Math.sin(angle)*pointY[i]; 73. pointY[i+1]=pointY[i]*Math.cos(angle)+pointX[i]*Math.sin(angle); 74. } 75. for(int i=0;i<360;i++) { 76. pointX[i]=0.5*pointX[i]+w/2; //坐标缩放、平移 77. pointY[i]=0.5*pointY[i]+h/2; 78. } 79. timer.start(); 80. } 81. public void actionPerformed(ActionEvent e) { 82. i=(i+1)%360; 83. earth.setLocation((int)pointX[i]-100,(int)pointY[i]-100); 84. } 85. }
地球图: 月亮图:
四、实验指导
如果一个圆的圆心是(0,0),那么对于给定的圆上的一点(x,y),该店按顺时针旋转a弧度后的坐标(m,n)有下列公式计算:
m=x*cos(a)-y*sin(a);
n=y*cos(a)+x*sin(a)。