java 多线程相关问题

java多线程相关问题

很多知识还是应该自己进行测试,看看结果,别人的看了印象不是太深刻。

java多线程实现的方法:
A, 集成Thread类: public class Thread1 extends Thread{}
B, 实现Runnable接口: public class Thread1 implements Runnable{}
两者之间的差别: 
A, java不能多继承,故在继承Thread类时候我们就不能再继承其他类了。
B, 实现Runnable接口能够更好的对同一个资源进行访问。
A比较容易理解,B呢?为什么会这样?
我们做一个测试:   恰好今天教师节,举个应景的例子。假设再幼儿园里面老师给同学发苹果,有多个老师,但是苹果数是一定的,那这就是一个多线程的问题。我们做如下测试:

public class Test{
	static class Teacher extends Thread{
		public Teacher(String temp){
			super(temp);
		}
		//苹果数量
		private int apple = 5;
		public void run(){
			while(true){
				if(apple>0){
					try {
						//让线程休眠1s  
						sleep(1000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					//老师进行分发
					System.out.println(Thread.currentThread().getName()+"开始分发苹果,剩余"+apple--);
				}
<span style="white-space:pre">				</span>else
<span style="white-space:pre">				</span>  break;
			}
		}
	}
	public static void main(String[] args0){
		Teacher teacher1 = new Teacher("Teacher1");
		Teacher teacher2 = new Teacher("Teacher2");
		Teacher teacher3 = new Teacher("Teacher3");
		teacher1.start();
		teacher2.start();
		teacher3.start();
	}
}
在上面的例子中大家会看到我们的逻辑是实例化多个teacher,那么在进行多个线程运行的时候,其实他们的占有各自的内存空间,彼此之间并没有什么直接联系。结果可以预见:
Teacher1开始分发苹果,剩余5
Teacher2开始分发苹果,剩余5
Teacher3开始分发苹果,剩余5
Teacher1开始分发苹果,剩余4
Teacher2开始分发苹果,剩余4
Teacher3开始分发苹果,剩余4
Teacher1开始分发苹果,剩余3
Teacher2开始分发苹果,剩余3
Teacher3开始分发苹果,剩余3
Teacher1开始分发苹果,剩余2
Teacher2开始分发苹果,剩余2
Teacher3开始分发苹果,剩余2
Teacher1开始分发苹果,剩余1
Teacher2开始分发苹果,剩余1
Teacher3开始分发苹果,剩余1

但是这样写多线程并不是正确的方式,待会我们会解析。可以发现,所有实例都是各做各的,并没有什么直接联系。这是因为单独实例化了多个对象,每个对象都独立存储栈中,栈中存储的变量也相互独立。所以都是各自完成自己的工作。

换一种方式,用实现runnable接口实现:
class Teacher implements Runnable{
		private int apple = 10;
		@Override
		public void run() {
			// TODO Auto-generated method stub
			while(true){
				if(apple>0){
					try { 
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName()+"开始分发苹果,剩余"+apple--);
				}
				else
					break;
			}
		}
	}
public class Test{
	public static void main(String[] args0){
		Teacher teacher = new Teacher();
		Thread thread1 = new Thread(teacher,"Teacher1");
		Thread thread2 = new Thread(teacher,"Teacher2");
		Thread thread3 = new Thread(teacher,"Teacher3");
		thread1.start()<span style="font-family: Arial, Helvetica, sans-serif;">;</span>
		thread2.start():
		thread3.start();
	}
}
这样,其实可以看出来,虽然我们实例化了多个Thread,但是我们并只是相当于使用Thread来运行我们的同一个teacher实例,所以结果:
Teacher1开始分发苹果,剩余10
Teacher1开始分发苹果,剩余9
Teacher1开始分发苹果,剩余8
Teacher1开始分发苹果,剩余7
Teacher1开始分发苹果,剩余6
Teacher1开始分发苹果,剩余5
Teacher1开始分发苹果,剩余4
Teacher1开始分发苹果,剩余3
Teacher1开始分发苹果,剩余2
Teacher1开始分发苹果,剩余1
Teacher3开始分发苹果,剩余0
这才是我们预期的结果,但是还是不正确,如果我们把sleep的时间改大一点就会出现问题。这是因为我们在操作的时候并没有获取对象锁,那么就可能存在这样两个线程,A和B,A判断之后执行--操作之前,B也进行了判断,发现apple=2,那么两个线程同时进行了--操作,则就导致了上面的情况,出现了apple=0的错误。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值