多线程实验
实验六 多线程实验
一、实验目的
练习多线程类的两种实现方法,理解多线程程序的生命周期
二、实验内容
编写一多线程程序,实现如下功能:
(1)一个线程进行阶乘和的运算(1!+2!+3!+……+12!),每次阶乘计算时间随机间隔0.5-1秒;
(2)另一个线程每隔1秒时间读取上个线程的运算结果和计算进程,并在图形界面中实时显示结果。
三、实验设计
(反映设计原理、设计方法、设计过程、设计结果)
1:首先在windowbuilder里面建立图形用户设计界面。
2:添加“多线程实验”字样,这里使用的是Components里面的Jlabel。
3:同样的方法,添加“计算进程”和“读取结果”,添加好以后,图形用户界面就会成下面这个样子。
4:接下来添加文本框,用来显示进程以及结果,文本框可以直接用Components里面的JtextField或者添加滚动条的面板,再用JtextArea,都可以显示你想要的结果,随便哪一种都可以。
5:同样的操作,计算进程和读取结果后面都应该有文本框,用来显示结果。下面就是添加好文本框的样子。
6:接下来需要一个进度条,进度条是Components里面的JProgressBar
7:最后还差一个启动按钮,用来控制进程,点击启动按钮,执行计算,用Compons里面的Jbutton作为按钮。
8:这样就设计好了图形用户界面
9:运行一下试一试,看看效果
四、实验过程
(反映实验的基本过程,重点体现实验中遇到的问题和解决方案)
1:设计好图形用户界面后,双击启动程序按钮,或者左边栏中打开按钮的事件,进入相应代码,这里只需要设计启动程序按钮的事件,来触发执行其他两个类的代码
2:首先是建立一个ComputeThread类,这个类用来编写运算并且将运算过程显示出来,在监听到启动按钮时,执行代码,并显示在读取进程的文本框里。
3:然后建立一个ReadThread类,这个类用来编写显示结果的代码,将每一小步的计算结果显示出来。
4:关于进度条,虽然没有完美的设定,还是简单写了一下,表示可以动的进度条。
五、实验结果
(应先列出测试数据,要写明实验的现象,实验数据的分析等)
测试样例:计算1!+2!++···+12!的值
单独的阶乘 |
值 |
求阶乘和 |
1! |
1 |
1 |
2! |
2 |
2 |
3! |
6 |
9 |
4! |
24 |
33 |
5! |
120 |
153 |
6! |
720 |
873 |
7! |
5040 |
5913 |
8! |
40320 |
46233 |
9! |
362880 |
409113 |
10! |
3628800 |
4037913 |
11! |
39916800 |
43954713 |
12! |
479001600 |
522956313 |
由于计算进程读取时间是随机的1到2秒,所以每次运行的结果不一样,阶乘和计算的结果不一样,但是阶乘的值如上表,只是不同的时间里加起来的结果不一样。
实验现象:
如上图所示,可以看到,在第一秒的时候,计算1!,结果为1,然后下一秒也就是第二秒的时候,计算2!并且加上1!结果为3 所以显示的是3,加下来是第四秒的时候,计算的是1!+2!+3!+4!,结果是33.
每一次运行的结果是不一样的,因为读取进程的时间间隔不同,计算结果的值也就相应的不同,但是每一部分计算的都是前面的阶乘相加,求得现在这个数的阶乘和,这样运行到最后,就可以求出12的阶乘和,并且显示出来进程以及结果。
六、讨论与分析
(主要部分:通过实验对课程知识点的理解;实验结果的分析;回答实验指导书的实验思考提出的问题等)
多线程主要是对于生命周期的理解很重要,什么时候线程执行,什么时候结束,什么时候执行多线程分开实现,这些都是在实际应用中对于多线程问题需要考虑的,不同的线程也就是设定的不同的类,在类里面执行不同的事件,以此来实现多个进程同时进行或者有顺序的进行。
七、附录:关键代码(给出适当注释,可读性高)
package test;
import java.awt.EventQueue;
import javax.swing.JFrame;
import java.awt.BorderLayout;
import javax.swing.JButton;
import javax.swing.JPanel;
import java.awt.FlowLayout;
import java.awt.Color;
import javax.swing.border.BevelBorder;
import javax.swing.JTextField;
import javax.swing.JPasswordField;
import javax.swing.JTextArea;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JProgressBar;
import javax.swing.JLabel;
public class Muti {
public JFrame frame;
JTextArea progress;
JTextArea result;
JProgressBar progressBar;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Muti window = new Muti();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public Muti() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 519, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
JLabel label = new JLabel("\u591A\u7EBF\u7A0B\u5B9E\u9A8C");
label.setBounds(175, -1, 118, 17);
frame.getContentPane().add(label);
JLabel label_1 = new JLabel("\u8BA1\u7B97\u8FDB\u7A0B");
label_1.setBounds(13, 38, 83, 17);
frame.getContentPane().add(label_1);
JLabel label_2 = new JLabel("\u8BFB\u53D6\u7ED3\u679C");
label_2.setBounds(13, 133, 83, 17);
frame.getContentPane().add(label_2);
progress = new JTextArea();
progress.setBounds(89, 28, 339, 68);
frame.getContentPane().add(progress);
result = new JTextArea();
result.setBounds(89, 123, 339, 40);
frame.getContentPane().add(result);
progressBar = new JProgressBar();
progressBar.setBounds(136, 178, 208, 14);
frame.getContentPane().add(progressBar);
JButton btnNewButton = new JButton("\u542F\u52A8\u7A0B\u5E8F");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
qidong();
}
});
btnNewButton.setBounds(159, 215, 123, 29);
frame.getContentPane().add(btnNewButton);
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void qidong() {//启动程序执行的事件
ComputeThread cal=new ComputeThread();//用ComputeThread建立一个对象
cal.start();//调用这个对象的start方法
ReadThread read =new ReadThread();//用读取ReadThread这个类创建一个读取的对象
Thread readthread=new Thread(read);//创建一个线程
read.setCalculate(cal,this);//调用线程中的读取
readthread.start();//然后开始执行不同的线程
}
}
package test;
public class ComputeThread extends Thread {
int j;
int sum;
double a = Math.random()*(1000-500)+500;
public void run() {
for(int i=1;i<13;i++){
sum = 0;
for(int j =1;j<i;j++) {
sum += jc(j);
}
try {
Thread.currentThread().sleep((long)a);
j=i;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public int jc(int n) {
if (n == 0 || n == 1)
return 1;
else
return n*jc(n - 1);
}
}
package test;
public class ReadThread implements Runnable{
ComputeThread ct;
Muti window;
void setCalculate(ComputeThread ct,Muti mt) {
this.ct = ct;
window = mt;
}
public void run() {
while(ct.j<=12) {
try {
Thread.currentThread().sleep(1000);
window.result.append(ct.sum+" ");
window.progress.append(ct.j+" ");
float m = (float)(ct.j);
int i = (int)((m/12)*100);
window.progressBar.setValue(i);
if(ct.j==12) {
break;
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
注:每个部分根据情况可以再分子标题,前提是层次清晰、逻辑性强。
实验六 多线程实验
一、实验目的
练习多线程类的两种实现方法,理解多线程程序的生命周期
二、实验内容
编写一多线程程序,实现如下功能:
(1)一个线程进行阶乘和的运算(1!+2!+3!+……+12!),每次阶乘计算时间随机间隔0.5-1秒;
(2)另一个线程每隔1秒时间读取上个线程的运算结果和计算进程,并在图形界面中实时显示结果。
三、实验设计
(反映设计原理、设计方法、设计过程、设计结果)
1:首先在windowbuilder里面建立图形用户设计界面。
2:添加“多线程实验”字样,这里使用的是Components里面的Jlabel。
3:同样的方法,添加“计算进程”和“读取结果”,添加好以后,图形用户界面就会成下面这个样子。
4:接下来添加文本框,用来显示进程以及结果,文本框可以直接用Components里面的JtextField或者添加滚动条的面板,再用JtextArea,都可以显示你想要的结果,随便哪一种都可以。
5:同样的操作,计算进程和读取结果后面都应该有文本框,用来显示结果。下面就是添加好文本框的样子。
6:接下来需要一个进度条,进度条是Components里面的JProgressBar
7:最后还差一个启动按钮,用来控制进程,点击启动按钮,执行计算,用Compons里面的Jbutton作为按钮。
8:这样就设计好了图形用户界面
9:运行一下试一试,看看效果
四、实验过程
(反映实验的基本过程,重点体现实验中遇到的问题和解决方案)
1:设计好图形用户界面后,双击启动程序按钮,或者左边栏中打开按钮的事件,进入相应代码,这里只需要设计启动程序按钮的事件,来触发执行其他两个类的代码
2:首先是建立一个ComputeThread类,这个类用来编写运算并且将运算过程显示出来,在监听到启动按钮时,执行代码,并显示在读取进程的文本框里。
3:然后建立一个ReadThread类,这个类用来编写显示结果的代码,将每一小步的计算结果显示出来。
4:关于进度条,虽然没有完美的设定,还是简单写了一下,表示可以动的进度条。
五、实验结果
(应先列出测试数据,要写明实验的现象,实验数据的分析等)
测试样例:计算1!+2!++···+12!的值
单独的阶乘 |
值 |
求阶乘和 |
1! |
1 |
1 |
2! |
2 |
2 |
3! |
6 |
9 |
4! |
24 |
33 |
5! |
120 |
153 |
6! |
720 |
873 |
7! |
5040 |
5913 |
8! |
40320 |
46233 |
9! |
362880 |
409113 |
10! |
3628800 |
4037913 |
11! |
39916800 |
43954713 |
12! |
479001600 |
522956313 |
由于计算进程读取时间是随机的1到2秒,所以每次运行的结果不一样,阶乘和计算的结果不一样,但是阶乘的值如上表,只是不同的时间里加起来的结果不一样。
实验现象:
如上图所示,可以看到,在第一秒的时候,计算1!,结果为1,然后下一秒也就是第二秒的时候,计算2!并且加上1!结果为3 所以显示的是3,加下来是第四秒的时候,计算的是1!+2!+3!+4!,结果是33.
每一次运行的结果是不一样的,因为读取进程的时间间隔不同,计算结果的值也就相应的不同,但是每一部分计算的都是前面的阶乘相加,求得现在这个数的阶乘和,这样运行到最后,就可以求出12的阶乘和,并且显示出来进程以及结果。
六、讨论与分析
(主要部分:通过实验对课程知识点的理解;实验结果的分析;回答实验指导书的实验思考提出的问题等)
多线程主要是对于生命周期的理解很重要,什么时候线程执行,什么时候结束,什么时候执行多线程分开实现,这些都是在实际应用中对于多线程问题需要考虑的,不同的线程也就是设定的不同的类,在类里面执行不同的事件,以此来实现多个进程同时进行或者有顺序的进行。
七、附录:关键代码(给出适当注释,可读性高)
package test;
import java.awt.EventQueue;
import javax.swing.JFrame;
import java.awt.BorderLayout;
import javax.swing.JButton;
import javax.swing.JPanel;
import java.awt.FlowLayout;
import java.awt.Color;
import javax.swing.border.BevelBorder;
import javax.swing.JTextField;
import javax.swing.JPasswordField;
import javax.swing.JTextArea;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JProgressBar;
import javax.swing.JLabel;
public class Muti {
public JFrame frame;
JTextArea progress;
JTextArea result;
JProgressBar progressBar;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Muti window = new Muti();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public Muti() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 519, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
JLabel label = new JLabel("\u591A\u7EBF\u7A0B\u5B9E\u9A8C");
label.setBounds(175, -1, 118, 17);
frame.getContentPane().add(label);
JLabel label_1 = new JLabel("\u8BA1\u7B97\u8FDB\u7A0B");
label_1.setBounds(13, 38, 83, 17);
frame.getContentPane().add(label_1);
JLabel label_2 = new JLabel("\u8BFB\u53D6\u7ED3\u679C");
label_2.setBounds(13, 133, 83, 17);
frame.getContentPane().add(label_2);
progress = new JTextArea();
progress.setBounds(89, 28, 339, 68);
frame.getContentPane().add(progress);
result = new JTextArea();
result.setBounds(89, 123, 339, 40);
frame.getContentPane().add(result);
progressBar = new JProgressBar();
progressBar.setBounds(136, 178, 208, 14);
frame.getContentPane().add(progressBar);
JButton btnNewButton = new JButton("\u542F\u52A8\u7A0B\u5E8F");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
qidong();
}
});
btnNewButton.setBounds(159, 215, 123, 29);
frame.getContentPane().add(btnNewButton);
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void qidong() {//启动程序执行的事件
ComputeThread cal=new ComputeThread();//用ComputeThread建立一个对象
cal.start();//调用这个对象的start方法
ReadThread read =new ReadThread();//用读取ReadThread这个类创建一个读取的对象
Thread readthread=new Thread(read);//创建一个线程
read.setCalculate(cal,this);//调用线程中的读取
readthread.start();//然后开始执行不同的线程
}
}
package test;
public class ComputeThread extends Thread {
int j;
int sum;
double a = Math.random()*(1000-500)+500;
public void run() {
for(int i=1;i<13;i++){
sum = 0;
for(int j =1;j<i;j++) {
sum += jc(j);
}
try {
Thread.currentThread().sleep((long)a);
j=i;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public int jc(int n) {
if (n == 0 || n == 1)
return 1;
else
return n*jc(n - 1);
}
}
package test;
public class ReadThread implements Runnable{
ComputeThread ct;
Muti window;
void setCalculate(ComputeThread ct,Muti mt) {
this.ct = ct;
window = mt;
}
public void run() {
while(ct.j<=12) {
try {
Thread.currentThread().sleep(1000);
window.result.append(ct.sum+" ");
window.progress.append(ct.j+" ");
float m = (float)(ct.j);
int i = (int)((m/12)*100);
window.progressBar.setValue(i);
if(ct.j==12) {
break;
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
注:每个部分根据情况可以再分子标题,前提是层次清晰、逻辑性强。