09 多线程

----------- android培训java培训、java学习型技术博客、期待与您交流! ------------

					   多线程


1、进程:当前正在执行的程序,代表一个应用程序在内存中的执行区域。

2、线程:是进程中的一个执行控制单元,执行路径。是CPU调度和分派的基本单位;
	 一个进程中如果只有一个执行路径,这个程序称为单线程;
	 一个进程中有多个执行路径时,这个程序成为多线程;
3、多线程的意义
	允许多个线程并发执行,提高程序运行效率。
	例如:迅雷多线程下载,QQ多个人同时聊天,凌波多个人同时共享屏幕
   
4、CPU执行原理
	class Demo extends Thread{
		private String name;
		Demo(String name){
			this.name = name;
		}
		public void run(){
			System.out.println("name="+"-------------"+name);
		}
	}
	class  ThreadDemo{
		public static void main(String[] args) {
			Demo d1 = new Demo("one");//创建了一个Thread类的子类对象
			Demo d2 = new Demo("two");
			d1.run();
			d2.run();
			for(int x=0; x<20; x++){
				System.out.println("main----"+x);
			}
		}
	}
	当创建了两个线程对象d1,d2后,这时程序就有了三个线程在同时执行。
	当主函数执行完d1.start(),d2.start()后,这时三个线程同时打印,结果比较杂乱,这是因为线程的随机性造成的;
	随机性的原理是:windows中的多任务同时执行,其实就是多个应用程序在同时执行
	而每一个应用程序都由线程来控制,所以windows就是一个多线程的操作系统,cpu是负责提供程序运算的设备。
	cpu特点:在某一个时刻,只能执行一个程序,所以多个程序执行并不是真正的同时执行。其实就是cpu做这快速的
		 切换完成的。只是感觉上同时而已.真正意义上的同时执行需要多个CPU,也就是现在的多核;

5、线程的创建
	继承Thread类:
	    子类覆盖父类中的run(),将线程运行的代码存放在run()中;
	    子类当父类用,创建子类对象就是创建一个线程;
	    通过调用start()开启线程;
	    特点:当类去描述事物,事物中有属性和行为。如果行为中有部分代码被多线程所执行,同时还在操作属性,
		      就需要该类继承Thread类,产生该类的对象作为线程对象。这样会导致每一个对象中都存储一份
		      属性数据,无法在多个线程中共享该数据,可以加上静态,虽然实现了共享但是生命周期过长;
		  如果一个类明确了自己的父类,就不能再继承Thread,或者一个类继承了Thread类后也同样不能继承别的
		      类,因为java不允许类的多继承;
		new Thread(new Runnable() {  
			public void run(){
				System.out.println("Runnable"); 
			}
		}) {
			public void run() {
				System.out.println("Thread");	
			}
		}.start();	//结果:Thread
		Thread类可以实现Runnable接口:Thread类中run()覆盖了Runnable接口中的run()
	实现Runnable接口:
	    子类覆盖接口中的run();
	    创建Thread对象时,将实现了Runnable接口的子类对象作为参数传递给Thread类的构造函数:
		这样相当于只创建一个对象,实现资源的共享,让多条线程共享一个资源;
	    thread类对象调用start()开启线程;
	线程的五种状态:
	    创建:start()
	    临时阻塞:CPU在执行某个线程时,其它线程都不会运行,具备执行资格,但是没有执行权
	    冻结:sleep()或wait(),时间到notify()
	    运行:run()或stop()
	    消亡:run()方法结束
	    sleep()需要指定睡眠时间,单位是毫秒;
	    特殊的状态:临时阻塞。具备了执行资格,但是还没有获取资源;

6、线程安全
	原因:多个线程并发操作同一对象,访问出现延迟。
	      线程随机性,一条线程的操作还没有结束,CPU切换到另一条线程工作,导致操作出错
	线程安全问题在理想状态下,不容易出现,但一旦出现对软件的影响非常大;

7、解决线程安全问题
      解决原理:让多条操作共享数据的代码在某一时间段被一个线程执行,执行过程中其它线程不参与运算;	
          同步代码块:	synchronized(对象) {
				需要同步的代码;
			}
		将访问数据的代码锁住,在同步代码块中的内容同一时间内只能一个线程执行;
		同步可以解决安全问题的根本原因就在那个对象上;该对象如同锁的功能;
          同步方法:方法上加synchronized,整个方法的代码都是同步的,只能一个线程运行,同步方法使用this作为锁;
      同步的前提:要两个或者两个以上的线程;多个线程使用的是同一个锁;
      同步的好处:同步的出现解决了多线程的安全问题;
      同步的弊端:当线程相当多时,每个线程都会去判断同步上的锁耗费资源,降低程序的运行效率;
      死锁:在多个线程并发执行使用多个锁来同步时,有可能互相冲突,导致程序无法继续执行(同步嵌套);
	    同步出现解决了线程安全问题,但是非常消耗资源,效率会降低并且容易引发死锁;

8、线程间通信
      在同步代码中可以使用锁对象的wait()方法让当前线程等待;
      使用锁对象的notify()方法可以将正在等待的线程唤醒;
      如果多个线程都在等待,notify()唤醒随机1个;
      notifyAll()方法可以唤醒所有在等待的线程;
      wait(),notify(),notifyAll(),这些用来操作线程存在与同步中,使用这些方法时必须要标识所属的同步的锁,
	  锁可以是任意对象,所以任意对象调用的方法一定定义Object类中;
      wait(),sleep()区别:
          wait():释放cpu执行权,释放锁;
	  sleep():释放cpu执行权,不释放锁;

9、JDK5之后的线程同步与通信
    同步:
	  使用java.util.concurrent.locks.Lock接口的实现类对象来进行同步;
	  ReentrantLock就是Lock的实现类,可以实现synchronized的功能;
	  在需要同步的代码块前后使用lock()和unlock()方法来完成同步;
	  unlock()最好放在finally中,因为如果上面代码抛出异常没有解锁;,会导致其它线程无法运行,程序卡死;
    通信:
	  使用Lock对象的newCondition()方法获取一个Condition对象,Condition对象可以控制指定线程的等待与唤醒;
	  await()方法可以控制线程等待;
	  signal()方法可以唤醒等待的线程;
	  signalAll()方法可以唤醒所有等待线程;

10、停止线程
      定义循环结束标记:因为线程运行代码一般都是循环,只要控制了循环即可;
      使用interrupt()中断:该方法是结束线程的冻结状态,使线程回到运行状态中来;
      注:stop()已经过时不再使用;

11、线程中方法
      currentThread():静态方法,返回当前线程对象的引用;
      getName(),setName():用来获取、设置当前线程的名字;
      sleep():控制线程休眠,单位为毫秒;
      setDaemon():将线程设置为守护线程。线程默认是非守护线程,守护线程不能单独执行;
      join():让出执行权,当前线程暂停,等待加入的线程运行结束,当前线程再执行;
      setPriority(int num):设置线程优先级;
      toString():返回该线程的字符串表示形式,包括线程名称、优先级和线程组;
      Thread(String name):构造函数,线程对象一建立就可以指定名称;
      setName(String name):自定义线程名字
	


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值