黑马程序员——Java之多线程(2)

------Java培训、Android培训、iOS培训、Net培训、期待与您交流! ------

 

 一、多线程的同步

       当多个线程操作同一个共享资源时,比如读写同一个变量,存在着资源竞争的问题。为了解决此类问题,需要使用同步机制。这就好比一个人上洗手间,这个人进入洗手间后将门锁上,当他出来时再将锁打开,然后其他让才可以进入。

 

(1)同步代码块

         在Java中提供了同步机制,可以有效地防止资源冲突。同步机制使用synchronizedz关键字。使用同步代码块的目的:阻止两个线程对同一个共享资源进行并发访问。

         同步代码块的语法格式:

synchronizedz(obj)

        {

           ....

           //此处的代码就是同步代码块

        }

示例:模拟火车站售票系统。

public class ThreadSafeTest implements Runnable{
    //设置当前总票数
	int num = 10;
	//重写run()方法,定义了线程的执行体
	public void run() {
		while (true) {
			//同步代码块
			synchronized ("") {
				if (num>0) {
				try {
					//设定线程睡眠的时间
					//由于线程休眠时可能被中断,所以需要捕获异常
					Thread.sleep(100);
				} catch (InterruptedException e) {
					
					e.printStackTrace();
				}
				System.out.println("车票还有"+num--+"张");
			    }
			}
		}
	}
			
	public static void main(String[] args) {
		//实例化类对象
		ThreadSafeTest t = new ThreadSafeTest();
		//以该类对象分别实例化4个线程
		Thread tA = new Thread(t);
		Thread tB = new Thread(t);
		Thread tC = new Thread(t);
		Thread tD = new Thread(t);
		//分别启动线程
		tA.start();
		tB.start();
		tC.start();
		tD.start();
  }
}

运行结果:

车票还有10张
车票还有9张
车票还有8张
车票还有7张
车票还有6张
车票还有5张
车票还有4张
车票还有3张
车票还有2张
车票还有1张

 

(2)同步方法

       当某个对象调用了同步方法时,该对象上的其他同步方法必须等待该同步方法执行完毕才能被执行。必须将每个能访问共享资源的方法修饰为synchronized。

       同步方法就是在方法前面修饰synchronized关键字的方法,其语法格式如下:

synchronizedz  void  f()

        {

           ....

          
        }

示例:

public class ThreadSafeTest implements Runnable{
    //设置当前总票数
	int num = 10;
	//定义同步方法
	public synchronized void doit(){
		if(num>0){
		try {
			Thread.sleep(10);
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("车票还有"+num--+"张");
		}
	}
	//重写run()方法,在run()方法中调用该同步方法
	public void run() {
		while (true) {
			doit();
		}
	}
	public static void main(String[] args) {
		//实例化类对象
		ThreadSafeTest t = new ThreadSafeTest();
		//以该类对象分别实例化4个线程
		Thread tA = new Thread(t);
		Thread tB = new Thread(t);
		Thread tC = new Thread(t);
		Thread tD = new Thread(t);
		//分别启动线程
		tA.start();
		tB.start();
		tC.start();
		tD.start();
	}
}

运行结果:

车票还有10张
车票还有9张
车票还有8张
车票还有7张
车票还有6张
车票还有5张
车票还有4张
车票还有3张
车票还有2张
车票还有1张

 

二、线程的通信

       在讲诉线程与进程的区别时已经讲解过,线程是共享相同的地址空间,并会协作完成一项任务的,因此线程之间必须能够通信。

       Java中提供了wait(),notify()和notifyAll()方法实现了线程间通信机制。这些方法在根类Object中是用final关键字声明的,因此所有的类都包含这些方法。需要说明的是这3个方法仅在synchronized修饰块中才能被调用。

       ①final void wait() throws InterruptedException方法 :通知当前的线程进入睡眠直到其他线程进入调用notify()唤醒它。在睡眠之前,线程会释放掉所占有的“锁标志”,则其占用的所有synchronized代码块可被别的线程使用。
       ②final void notify()方法:唤醒在该同步代码块中第一个调用wait()的线程(即第一个进入休眠状态的线程),并且这时会从线程等待池转移到锁标志等待池中,因为该线程没有立刻获取锁标志。

       ③final void notifyAll()方法:唤醒在该同步代码块中所有调用wait()的线程,并且会从线程等待池中所有该对象的所有线程转移至锁标志等待池中,因为这些线程没有获取锁标。


 

 


 

        

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值