目录
7-1 多线程计算 (30 分)
已知某学校有n名教师,学校有m名学生,学校搞学生民意调查,每一位学生为每一位老师都打分,学生所打的所有的分数都集中到一个数组中。数据存放规律是,前m个数据是对1号老师的打分,接下来m个数据是对2号老师的打分,以此类推。请设计一个多线程的算法,计算出每一位老师的总打分。
输入格式:
第一行输入教师数,第二行输入学生数,第三行输入所有n*m个打分(整型),各个分数之间以一个空格分隔
输出格式:
按照教师原来的顺序,每行输出每一位老师的得分
输入样例:
在这里给出一组输入。例如:
2
3
1 2 3 4 5 6
输出样例:
在这里给出相应的输出。例如:
6
15
答案:
import java.util.*;
public class Main {
//一定要抛出异常,否则是部分正确
public static void main(String[] args) throws InterruptedException{
Scanner sc = new Scanner(System.in);
int teacher =sc.nextInt();
int student =sc.nextInt();
//集合类型,方便删除和移动元素(此题要删除和移动元素)
ArrayList<Integer> num=new ArrayList<Integer>();
for(int i=0;i<student*teacher;i++) {
int a = sc.nextInt();
num.add(a);
}
Score score=new Score(num,teacher, student);
Thread t[]=new Thread[teacher];
for(int i=0;i<t.length;i++) {
t[i]=new Thread(score);
t[i].start();
}
}
}
class Score implements Runnable{
int teacher,student;
ArrayList<Integer> num=new ArrayList<Integer>();
public Score(ArrayList<Integer> num, int teacher, int student) {
//必须是this.XXX,否则结果是0,0
this.num = num;
this.teacher = teacher;
this.student = student;
}
public synchronized void run() {
int sum = 0;
for (int i = 0; i < student; i++) {
//返回此列表中指定位置的元素,并相加
sum += num.get(0);
//删除该列表中指定位置的元素
num.remove(0);
}
System.out.println(sum);
}
}
集合ArrayList
remove(),get(),add()
多线程
抛出异常
synchronized
结果说明
当两个并发线程(thread1和thread2)访问同一个对象(Score)中的synchronized代码时在同一时刻只能有一个线程得到执行,另一个线程受阻塞,必须等待当前线程执行完这个代码块以后才能执行该代码块。Thread1和thread2是互斥的,因为在执行synchronized代码块时会锁定当前的对象,只有执行完该代码块才能释放该对象锁,下一个线程才能执行并锁定该对象。Java中Synchronized的使用https://blog.csdn.net/qq_38011415/article/details/89047812
synchronized与Lock的区别
java内置锁是一个互斥锁,这就是意味着最多只有一个线程能够获得该锁,当线程A尝试去获得线程B持有的内置锁时,线程A必须等待或者阻塞,知道线程B释放这个锁,如果B线程不释放这个锁,那么A线程将永远等待下去。(目的:只有一个线程可执行)
java中同步锁synchronized与Lock的区别https://blog.csdn.net/gm371200587/article/details/88173030
7-2 试试多线程 (30 分)
编写4个线程,第一个线程从1加到25,第二个线程从26加到50,第三个线程从51加到75,第四个线程从76加到100,最后再把四个线程计算的结果相加。
输入格式:
无
输出格式:
最终结果
输入样例:
无
输出样例:
5050
答案:
public class Main {
public static void main(String[] args){
Add a1 = new Add(1);
Add a2 = new Add(26);
Add a3 = new Add(51);
Add a4 = new Add(76);
try {
a1.start();
a2.start();
a3.start();
a4.start();
a1.join(); //等待当前的线程执行结束
a2.join();
a3.join();
a4.join();
}catch(Exception e) {
e.printStackTrace();
}
Add.print();
}
}
class Add extends Thread{
public static int sum=0;
public int count=0;
//public static int count=0;不对
//静态变量被所有对象共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。
Add(){
}
Add(int temp){
count = temp;
}
//重写run方法
public void run() {
int i=0;
while(i<25) {
sum+=count;
count++;
i++;
}
}
public static void print() {
System.out.println(sum);
}
}
static
static修饰成员变量:
static修饰的变量也称为静态变量,静态变量和非静态变量的区别是:静态变量被所有对象共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。
static成员变量的初始化顺序按照定义的顺序进行初始化。java static关键字的作用是什么?https://www.php.cn/java/guide/462574.html
7-3 创建一个倒数计数线程 (40 分)
创建一个倒数计数线程。要求:1.该线程使用实现Runnable接口的写法;2.程序该线程每隔0.5秒打印输出一次倒数数值(数值为上一次数值减1)。
输入格式:
N(键盘输入一个整数)
输出格式:
每隔0.5秒打印输出一次剩余数
输入样例:
6
输出样例:
在这里给出相应的输出。例如:
6
5
4
3
2
1
0
答案:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int N=sc.nextInt();
Test t=new Test(N);
Thread th=new Thread(t);
th.start();
}
}
class Test implements Runnable {
public int M;
Test(){
}
Test(int N){
M = N;
}
public void run() {
for(int i=M;i>=0;i--){
System.out.println(i);
try
{
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Thread.sleep()