----------- android
培训、java培训、java学习型技术博客、期待与您交流! ------------
多
线程:
	概念:应用程序有多条执行路线。
	进程:当前正在运行的应用程序。
	线程:进程的执行单元。或者说,它就是一条执行路线。
	怎么用多线程呢? 或者说,多线程的实现方式是怎么样的?
java是不能直接调用操作系统属性的,但是可以通过调用其他语言来间接的调用操作系统的功能。
Thread类:
	同一个线程对象,调用两次start()方法,程序会抛
异常。
			IllegalThreadStateException:线程状态不正常。
	如何获取线程的名字以及重命名?
		获取:public final String getName();  获取当前线程的名字。名字的格式:Thread+编号(从0开始的。)
		重命名:public final void setName(String name);
	什么时候使用多线程?
		为了提高效率的时候。
		当我们要操作的代码的内容比较多(耗时),
循环的次数比较多的时候。就可以考虑使用多线程。
	
理解多线程的一个误区?
		每一个线程都会消耗
内存资源,并不是线程越多越好。
	线程执行的随机性是怎么回事?
		程序的执行,其实就是在抢占CPU资源,CPU是在各个程序之间做高效的切换。
		(线程执行的随机性是因为CPU的切换)
	
	第一种实现方式:
		1、
自定义一个类来继承Thread类。
		2、子类重写Thread类中的run()方法。
		3、让线程启动并执行。
			线程启动不能直接调用run()方法,要调用strat()。
			而start()这个方法做了两件事:
				1、让线程启动。
				2、自动调用run()方法。
		采用第1种创建线程的方式创建3个线程,分别设置线程名字为 : 曹操,刘备,孙权. 然后调用start()方法运行.
		
	第二种实现方式:
		1、自定义一个类My
Runnable去实现Runnable
接口。
		2、重写run()方法。
		3、创建该类MyRunnable的实例。
		4、把类MyRunnable的实例做为Thread类的构造参数传递,创建Thread对象。
		注意事项:
			因为我们的自定义的类MyRunnable只实现了Runnable接口,并没有直接继承Thread类。所以Thread类里边的方法,他是不能直接用。
				public static Thread currentThread();
	既然已经有了继承Thread类的实现方式,为什么还要提供实现Runnable接口呢?
		A:避免了单继承的局限性。
		B: 实现接口Runnable的方式,创建了一个资源对象,节省资源。实现了数据和操作的分类。(掌握)
	需求:线程的第2种方式实现线程,并给两个线程分别设置名字为 天成,八戒,然后运行两个线程。
用多线程模拟窗口卖票。
	第一种方式:自定义一个类,继承Thread类。
	第二种方式:自定义一个类,来实现Runnable接口。
为什么我们在用多线程模拟窗口卖票的时候,会出现重复数值以及负数呢?
	因为线程执行的随机性和延迟性,导致线程访问共享数据的时候出了问题。
	public static void sleep(long millis);   让线程睡一会,睡多长时间呢?看给定的毫秒值。
	为什么会出现负数?
		//如果此时,四个线程对象都抢到了CPU资源,会出现:
				/**
				 * 此时tickets的值为1
				 * t1:第1张票,  tickets值为0
				 * t2:第0张票,  tickets值为-1
				 * t3:第-1张票,  tickets值为-2
				 * t4:第-2张票,  tickets值为-3
				 */
	为什么会出现重复值?
		关键点:tickets--
		他其实做了三件事:
			A:读取tickets变量的值。
			B:修改tickets变量的值。
			C:把修改后的值赋值给tickets变量。
		如果当线程t1执行完A步骤,还没有来得及执行B的时候,
		如果线程t2抢到了CPU资源,这个时候就会出现重复值的情况。
	
怎么解决呢?
	在有可能会出问题的代码上加一个锁。
	
	怎么判断多线程有可能出问题的代码?
		1、是否有共享数据。
		2、是否有多条语句操作共享数据。
		3、是否是在多线程环境中。
	怎么加锁。(
同步机制,同步代码块,加锁)
		synchronized(锁对象)
		{
			有可能出现问题的代码。
		}
	锁对象:因为我们不知道是什么类型的,所以这里给了一个Object。
		两个状态:开,关。	
注意:多线程加锁必须是同一把锁。
	
	同步代码块的锁对象是什么类型?
		可以是任意类型。
	同步方法:在方法上加锁。
		格式:推荐在方法的返回值的数据类型前加synchronized。
			举例: public synchronized void show(){}
		同步方法的锁对象是谁呢?
			就是this对象。
	
静态方法的锁对象是谁呢?
		就是该类的字节码文件对象。
		 类名.
class
既然有同步代码块了,又有同步方法,我们使用谁呢?
	同步的代码越少越好。所以,一般我们都来是用同步代码块。
	但是,有些时候,一个方法里边的代码都需要被加锁,那我们就可以考虑使用同步方法。
面试题:
	写一个死锁的代码。
用学生类模拟线程间通信问题。
	线程间通信:就是指不同线程间对共享数据进行操作。
	我们用学生类来模拟的时候,需要创建哪些类呢?
		学生类:Student
		对学生赋值的类: SetStudent
		获取学生信息的类:GetStudent
		测试类:Test
刚才,我们在测试的时候,
发现一个问题,打印的数据,姓名和年龄不匹配?
	怎么产生?
		原因是因为线程的随机性。
	怎么解决?
		给所有的操作都加锁,注意,一定要给同一个锁对象,这个时候,我们的问题就解决了。
		但是有有又一个新的问题?
			我们发现数据是成片输出的,原因就是当线程对象抢到CPU资源的那一刻,足够它做好多事情了。
	新的需求:
	让刘意,林青霞,依次输出。
		用等待唤醒机制来处理。
		在处理之前,我们先说一个小问题:之前我们写的程序,是无限的在赋值和取值。
		正常的逻辑:
			针对输出:如果有数据,我们就输出。如果没有,就等待设置数据。
				(比如说,咱们去买票,如果有,我们就直接买了,如果没有,就等着出票)
			针对设置:如果有数据,就等待输出,如果没有,就设置。
				(比如说:火车站售票,有人来买,如果没票,我就造票)
		唤醒机制:
			Object类中的两个方法:
				public void wait();   让线程处于等待状态。
				public void notify(); 唤醒正在等待的线程。
	面试题:	
		wait()和sleep()的区别?
		wait():是Object类中的方法,是不需要传递参数的,会释放资源,然后让出CPU资源。
		sleep():是Thread类中的静态方法,是需要传递参数的。不会释放资源。
	
1、模拟卖票,用同步代码块处理一下。
2、用唤醒机制模拟写一下,用学生类模拟线程间的通信。
线程的优先级:
	public final int getPriority();  获取线程的优先级。
	public final void setPriority(int test);  更改线程的优先级。
	注意:
		1、线程的优先级默认是5,范围是1-10.
		2、线程的优先级越高,并不代表者线程一定第一个执行。
			而是说,线程的优先级越高,能在一定的基础上,让该线程获取到更多的执行权。
线程的拓展知识:
	暂停线程:
		public static void yield();   暂停当前正在运行的线程,并执行其他线程。
		注意事项:	
			一定程度上,可以让线程运行的更和谐一点,防止出现成片的同一线程的数据。
			但是,他不能保证实现数据依次出现,所以,如果需要依次输出数据,还是要
			采用等待唤醒机制。
	加入线程:
		public final void join();  等待线程终止。
		注意事项:	
			当在加入一个线程之前,该线程必须先启动。
		效果:
			一旦有join线程加入,其他线程必须等待,等该线程执行完毕,其他线程才开始执行。
		用法:
			当一个线程需要在某个线程执行完之后再执行,就可以用该方法。
	守护线程:
		main函数本身也是一个线程。
		main函数是程序的主入口。
		public final void setDaemon(boolean on);  设置线程为守护线程。一旦前台(主线程)线程结束,守护线程跟着都全部结束。
		
	
	
	
	
----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------