java线程相关

                                                  Java线程相关(Thread和Runnable)

 

               随便打开一个应用程序,即使这个程序很小,它也可能是由N多个线程所构成,在没有线程之前,我们用进程作为OS(操作系统)能够拥有资源和独立运行的基本单位。 我们要讨论的线程是比进程更小的,能够独立运行和拥有资源的基本单位。

               说到线程,我们就得分析一下一个线程的各种状态,它大体上可以分为以下几种:

     1 执行状态:线程获得了处理机正在运行。

     2 阻塞状态:线程因为某种原因而暂停运行。

     3 就绪状态:线程已经准备好运行,只要分配cpu就可以运行。

              既然我们知道了线程能够拥有资源和独立运行的基本单位,那么对于N个线程需要对一个相同的资源进行访问的情况会遇到什么问题呢。让我们看看下面的代码:               

 

public class RunnableTest implements Runnable{
	private int a = 0;
	public void run() {
		while(a>-10){
			a--;
			System.out.println("a" + "的值为" + a);
		}
	}
}
 
public class ThreadTest extends Thread {
	private int a = 0;
	public void run() {
		while (a > -10) {
			a--;
			System.out.println("a" + "的值为" + a);
		}
	}
}
              上面是实现多线程的两种方法,其中一种为继承Thread类,另一种为实现Runnable接口。但不论哪一种方法,进行下面的测试
public class Test {
	public static void main(String[] args) {
		ThreadTest thread_0 = new ThreadTest();
		new Thread(thread_0).start();
		new Thread(thread_0).start();
//		RunnableTest rt = new RunnableTest();
//		new Thread(rt).start();
//		new Thread(rt).start();
	}
}
  多次运行可能会有一种下面状况。
a的值为-2
a的值为-2
a的值为-3
a的值为-4
a的值为-5
a的值为-6
a的值为-8
a的值为-7
a的值为-9
a的值为-10

                 出现了两个a的值为-2。我们的计算机是分时操作系统,N个线程并发运行的时候,线程1可能执行到了a--的时候,它的时间片用完了。那么轮到了线程2执行,线程2也要执行a--后运行System.out.println("a" + "的值为" + a);语句,这时候的a就变为-2,如果此时线程2的时间片用完,那么又回到线程1执行,此时该执行System.out.println("a" + "的值为" + a);于是就会得到输出了两次a的值为-2的话。这显然不是我们所预期的。

                假设我们利用多线程卖票,这样的话我们可能卖出两张相同的票。这不科学。那么如避免这种情况的发生呢。大体上有下面几种方法:

                 1:Synchronized关键字。即在方法前面加上关键字synchronized,某个线程在调用被它修饰的方法前会检查是否有其他线程在用此方法,这样可以避免上面的问题。

 

                  2:Lock接口。Lock lock = new ReentrantLock();可以得到一个实现Lock的对象。这个可以在方法中给某一部分加锁,也可以实现资源的互斥共享。

 

	public synchronized void run() {
		while (a > -10) {
			a--;
			System.out.println("a" + "的值为" + a);
		}
	}
 
	private int a = 0;
	Lock lock = new ReentrantLock();
	public  void run() {
		while(a>-10){
			lock.lock();
			a--;
			System.out.println("a" + "的值为" + a);
		}
	}
      运行结果为:
a的值为-1
a的值为-2
a的值为-3
a的值为-4
a的值为-5
a的值为-6
a的值为-7
a的值为-8
a的值为-9
a的值为-10
                  后来经老师提醒我用过lock方法后需要unlock,于是我就对上面的代码做了如下改动:
        private int a = 0;
	Lock lock = new ReentrantLock();
	public  void run() {
		while (a > -10) {
			lock.lock();
			try {
				a--;
				System.out.println("a" + "的值为" + a);
			} catch (Exception e) {
                        } finally {
				lock.unlock();
			}
		}
                 结果输出却是a从-1到-11。我测试了半天,发现输出a的值为-10之后且执行完lock.unlock()之后又多执行了一个a--。
                  这个是因为我的锁加的地方是在while循环里面,可能会当a=-9的时候其中一个线程停止而另一个线程也正好进来了。。。结果就会得到-11的结果,由此我们可以得出加锁之前一定要找到正确的加锁位置。并且加锁之后一定要释放锁。锁对象,我用于加锁的所对象应该是唯一的,即,在这种情况下我的
                     Lock lock = new ReentrantLock();
应该作为一个全局变量来使用。这个道理就好像对于同一个房间要用同一把锁而不是多把一样。
                   但是在上面的代码中,我忽视了
                       上面就是线程并发遇到的最基本的问题以及解决此问题的基本方法。如有不对之处,请大家指正。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值