Java多线程——计算1-20阶乘和

Java多线程--计算1-20的阶乘和

  • 一、总体思路
    • 效果预览
    • 线程分工
  • 二、设计线程类
    • GUI
    • Thread
    • Runnable
  • 三、总结

一、总体思路

初次学习Java的时候,学习了多线程的理论知识后,就开始练习创建线程的两种方法,即通过继承Thead类构造线程 和 通过实现Runnable接口构造线程。大家应该都遇到过这样的练习题:用上述两种方法创建线程,分别实现计算和获取计算结果,计算的内容便是1-20的阶乘和,再用一个图形用户界面把相关结果按一定要求显示出来。

效果预览

此处的图形用户界面类似下图:

Java多线程——计算1-20阶乘和_第1张图片
当用户按下“开始计算”按钮时,逐步显示计算计算信息,从此可以看出线程进行的过程。

线程分工

这里一共有三个线程,1:GUI的主线程;2:继承Thread类的线程;3:实现Runnable的类的线程。具体分工如下:两个线程中的任意一个用来单纯实现计算功能,另一个作为连接的桥梁,获取计算线程的计算结果,并将其显示到GUI主线程的界面中去。至于GUI,当然就是显示线程的作用了。

二、设计线程类

GUI

创建GUI的简单方式就是下载一个Window Builder插件到eclipse中,新建的时候,选择file——new——other——WindowBuilder——Swing Designer——Application Window新建一个window应用程序。当然你也可以选择SWT Designer,只是这里面有的Swing里面都有。你更可以选择不使用插件,这时候你的代码就会是类似于这样的(用Java写记事本程序的代码片段):

    public int num1 = 0,num2 = 0,result = 0;//保存运算整数
	public String bufferString = "";//获取文本框中的字符串
	public String operString = "";//运算符
	JFrame jFrame;
	Container contentPane;
	public JTextField jTextField;//文本框
	public JButton b0,b1,b2,b3,b4,b5,b6,b7,b8,b9;//数字按钮
	public JButton bPlus,bReduce,bRide,bDivede;//加、减、乘、除
	public JButton bEqual,bReset;//等号、复位
	public JPanel jPanel1,jPanel2;//设置两个Panel

你就感受不到自动生成的乐趣,而是要把所有的东西都手动敲出来。。。想想就脑阔痛啊。不过好处是,你可以把这个过程的原理了解清楚,这对初学Java的同学是有很大帮助的。

好了,在这里,GUI的设计主要就是界面和卫唯一的一个事件–按钮事件,注册一个ActionLitsener就可响应它了,具体做法见代码吧:

public void actionPerformed(ActionEvent e) {
			CoutingThread ct = new CoutingThread();//创建thread对象
				
			ct.start();//用对象调用start方法,启动线程,执行run方法的内容
				
			Thread reader  = new Thread(new Start());//创建线程对象
				
			reader.start();
		}

Thread

这里就用Thread的子类线程来实现计算功能吧。计算的代码不难,一个循环就能搞定,但是如果要获取每次加法的结果的话,就要考虑怎么把值传给获取线程。这时候你需要一个数组来帮助你,把每次加法的结果存到数组里,然后每次取数的时候取相应位置上的元素,再加以显示就完事了。代码类似下方:

public void run() {
		//for(int i =1;i<=20;i++)
		//{
			//result += i;
			//step++;
			//ex = i+"";
		//}
		//这是1-20加法的简单代码,如果一开始觉得阶乘难于实现,可以先做整数的简单加法
		long mul = 1; //保存阶乘数
		
		result = new long[30];//数组保存每次加法的结果
		result[1] = 1;//从2开始循环,因此把1号位的初值赋好,下同
		
		step  = new int[30];//保存计算进度(1-20)
		step [1] = 1;
		
		ex = new String[30];//字符串数组保存计算表达式
		ex[1] = 1+"!";
		
		for(int i = 2; i <= 20; i++)
		{
			try {
				Thread.currentThread().sleep((int)(Math.random()*500)+500);
				//设置休眠时间为0.5-1.0秒的随机数
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			mul = mul*i;//设置阶乘数
			
			result[i] = result[i-1] + mul;//设置计算结果
			
			step[i] = step[i-1]+1;//设置进度条

			ex[i] =  ex[i-1] +"+" + i +"!";//设置计算表达式
		}
		
	}

当然,如果你在计算线程里面完成了显示功能,就不用考虑这么多了。

public void run() {
		long s = 1;//长整型储存计算结果
		for(i=1; i<=30; i++){
			if(str1.equals("")){//判断是否是第一个显示的数据
				str1 = i + "!";
			}else{
				str1 += "+" + i + "!";
			}
			//long s = 1;
			//for(int j=1; j<=i; j++){
				s *= i;
		//	}
			result += s;
			threadFrame.jTextField1.setText(str1);
			//显示计算表达式
			threadFrame.jProgressBar.setValue(i);
			//显示进度
			try {
				Thread.sleep((long)(500 + 500 * Math.random()));
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				System.out.println("第1个线程休眠时出错!");
				//处理异常
			}
		}	
	} 

Runnable

桥梁线程要做的就是从一个线程里获取数据显示到另一个线程中。需要注意的是,你要将该线程中需要用的其他两个线程的对象设为public,即扩大其范围。并在获取线程中的run方法外将其设为属性,具体做法如下:

	ComputeThread computer;
	computeApp window;
	ReadRunnable(ComputeThread computer,computeApp window){
		this.computer = computer;
		this.window = window;
	}

这里使用了构造方法给两个线程的对象完成初始化工作。
完成连接的代码如下:

	public void run() {
		// TODO Auto-generated method stub
		try {
			for(int n = 1; n<=20; n++) 
			{
				Thread.currentThread().sleep(1000);
				window.progressbar.setValue(computer.step[n]);//显示进度条
				window.textex.setText(computer.ex[n]);//显示计算表达式
				window.textresult.setText(computer.result[n]+"");//显示计算结果
			
			}
		
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

三、总结

综合性实验,总体思路要清晰,细节也很重要。连接线程是核心,计算也是核心。在这里我就是想分享一下自己的计算方法,即用数组存放数据,这也是数据处理的方法技巧。当然算法千万种,哪一款适合你就需要你自己去摸索和选择。

个人总结,有错误还请指出~

你可能感兴趣的:(java程序)