Java基础-线程(十个线程实现1~100求和)

这道题我大概搞了两个小时左右吧。
可是我发现总是不对,最后发现我做不出来了,因为我并未真正搞清整个程序的执行,以及对那些关键词(我指的是synchronized、wait()、notify()等这些玩意儿)的理解和使用都不清楚,更别说写出来整个程序了。

public class Forth2 {
	public static void main(String[] args) {
		MyRunnable3 mr = new MyRunnable3();
		Thread t1 = new Thread(mr, "Thread1");
		Thread t2 = new Thread(mr, "Thread2");
		Thread t3 = new Thread(mr, "Thread3");
		Thread t4 = new Thread(mr, "Thread4");
		Thread t5 = new Thread(mr, "Thread5");
		Thread t6 = new Thread(mr, "Thread6");
		Thread t7 = new Thread(mr, "Thread7");
		Thread t8 = new Thread(mr, "Thread8");
		Thread t9 = new Thread(mr, "Thread9");
		Thread t10 = new Thread(mr, "Thread10");
		t1.start();
		t2.start();
		t3.start();
		t4.start();
		t5.start();
		t6.start();
		t7.start();
		t8.start();
		t9.start();
		t10.start();
		mr.printSum();
		
	}
}
class MyRunnable3 implements Runnable {
	static int[] sum = new int[10];
	static int[] thread = {1, 11, 21, 31, 41, 51, 61, 71, 81, 91};
	public synchronized void run() {
		while (true) {
			if (!Thread.currentThread().getName().equals("Thread1")) {
				try {
					this.wait();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
			} else if (thread[0] <= 10)
			{
				sum[0] += thread[0]++;
				this.notifyAll();
			}
				
			if (!Thread.currentThread().getName().equals("Thread2")) {
				try {
					this.wait();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
			} else if (thread[1] < 20)
			{
				sum[1] += thread[1]++;
				this.notifyAll();
			}
			
			if (!Thread.currentThread().getName().equals("Thread3")) {
				try {
					this.wait();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
			} else if (thread[2] <= 30)
			{
				sum[2] += thread[2]++;	
				this.notifyAll();
			}
			
			//下面的是未修改为上面做法的时候,知道全部修改后也不对,所以放弃修改了。。。
			if (Thread.currentThread().getName() == "Thread4") {
				if (thread[3] <= 40)
					sum[3] += thread[3]++;
			}
			if (Thread.currentThread().getName() == "Thread5") {
				if (thread[4] < 50) 
					sum[1] += thread[4]++;
				
			}
			if (Thread.currentThread().getName() == "Thread6") {
				if (thread[5] <= 60) 
					sum[2] += thread[5]++;		
			}
			if (Thread.currentThread().getName() == "Thread7") {
				if (thread[6] <= 70)
					sum[0] += thread[6]++;
			}
			if (Thread.currentThread().getName() == "Thread8") {
				if (thread[7] < 80) 
					sum[1] += thread[7]++;
				
			}
			if (Thread.currentThread().getName() == "Thread9") {
				if (thread[8] <= 90) 
					sum[2] += thread[8]++;		
			}
			if (Thread.currentThread().getName() == "Thread10") {
				if (thread[9] <= 100) 
					sum[2] += thread[9]++;		
			}
		}
	}
	public void printSum() {
		System.out.println(sum[0]);
		System.out.println(sum[1]);
		System.out.println(sum[2]);
		System.out.println(sum[3]);
		System.out.println(sum[4]);
		System.out.println(sum[5]);
		System.out.println(sum[6]);
		System.out.println(sum[7]);
		System.out.println(sum[8]);
		System.out.println(sum[9]);
		System.out.println(sum[0] + sum[1] + sum[2] + sum[3] + sum[4] + sum[5] + sum[6] + sum[7] + sum[8] + sum[9]);
	}
}

看了正确答案后,有以下感想:
1、没有完全把握住封装思想,没有养成在写程序前先进行思考的习惯:
对于每一组的相加操作,应该找到规律,然后将其封装为一个方法!这样会使得程序更加简单。
2、join()的必要:通过for循环中的join()可以确保这十个线程全部执行完后,再执行主线程的打印语句,否则,十一个线程(10+主线程)的执行顺序是不确定的,这会使得最后的打印结果出错。
【注意:虽然有for循环依次执行每个线程的join,也就是说创建的十个线程依次插入到执行序列上,但每一组的打印结果并非是按照顺序有小到大的打印出来。因为可能在此之前就已经执行完了这个线程(也就是说,这时候已经打印出了该组的和sum),所以当它执行到join语句时,它从上次线程停止的地方继续执行,但已经发现自己不符合run的执行条件了,所以,join语句对处于这种情况的线程没有影响。只有调用join的线程还可以继续在被执行时,join才真正起到了作用——让该线程一直执行,直至不符合条件为止,期间不允许其他线程插入。这样,每一组的结果的打印顺序实际上是随机的呢。】
【也可以这样理解:一共十一个线程,这十一个线程其实总是随机执行的(取决于CPU给谁执行机会),但是我们想要的结果是让我们创建的那十个线程正确执行出结果,最后执行一次主线程的打印语句就完事。于是,我们在主线程上加了join语句,让这十个线程都插一次队,执行完了的线程就没啥事了,没执行完了的就继续执行,直至不符合run中的条件。最后,主线程输出最后的结果。】

package chapcter5;

public class Accumulator extends Thread { 
	/*可以直接让主函数所在的类继承Thread类!
	 * 可以理解为,对于这道题的解答,直接放在了一个类里。
	 * 
	 * */
	
	private int startNum;
	public static int sum;
	public Accumulator(int startNum) {
		this.startNum = startNum;
	}
	public static synchronized void add(int num) {		//add()被设置为线程安全的!该方法不能被多个线程同时执行!
		sum += num;
	}
	public void run() {
		int sum = 0;
		for (int i = 0; i < 10; i++) {
			sum += (startNum + i);						//找到规律...
			/* 执行效果:(这是自己不容易想到的。所以在写程序前要思考!寻找每组连加的规律!才能使代码变得简单啊)
			   *  第一组:0 + (1+0)+(1+1)+(1+2)+...+(1+9) = 1 + 2 + 3 + ... + 10
			   *  第二组:0 + (11+0) +(11+1)+(11+2)+...+(11+9) = 11 + 12 + 13 + ... + 20
			 * ...
			 * */
		}
		System.out.println(sum);
		add(sum);										//将每组的结果相加
	}
	public static void main(String[] args) {	
		Thread[] threadList = new Thread[10];			//创建Thread数组!
		for (int i = 0; i < 10; i++) {					//这个for循环的作用是开启十个线程!
			threadList[i] = new Accumulator(10 * i + 1);//找到技巧...
			/* 这里将分别传入每组的初始数据。
			 * */
			threadList[i].start();
		}
		for (int i = 0; i < 10; i++) {
			try {
				threadList[i].join();
				 /*
				 * 谁调用join()谁就优先执行。也就是说,threadList[i]线程一直执行自己的run()方法,直至不符合条件使得该线程结束。
				 * 事实上,在此之前每个线程执行到何种地步是不需要关心的。而这里的for循环可以确保每个线程都执行完了。
				 * 那么这个for循环语句的执行顺序是:先i = 0,使得threadList[0]一直执行其run()直至完毕后,再使得i = 1...这样进行下去???
				 * 
				 * */
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} 						//
		}
		System.out.println("1 + 2 + 3 + ... + 100 = " + sum);
	}
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值