多线程

	
	1、多线程:一个应用程序有多条执行路径
		进程:正在运行的应用程序(是系统进行资源分配和调用的独立单元,每一个进程有它自己的内存空间和系统资源)
		线程:进程的执行单元(程序执行的任务),执行路径
		
		单线程:一个应用程序只有一条执行路径
		多线程:一个应用程序有多条执行路径(一个程序执行多个任务)
		
		并行和并发:
			前者是逻辑上同时发生,指在某一个时间内同时运行多个程序。
			后者是物理上同时发生,指在某一个时间点同时运行多个程序。
			
		多进程的意义?
			提高CPU的使用率
		多线程的意义?
			提高应用程序的使用率
	2、Java程序的运行原理及JVM的启动是多线程的吗?
		A:Java命令去启动JVM,JVM会启动一个进程,该进程会启动一个主线程,主线程去调用某个类的 main 方法。所以 main方法运行在主线程中。
		B:JVM的启动是多线程的,它最少有两个线程启动,主线程和垃圾回收线程。
	3、多线程的实现方案(掌握)
		A:继承Thread类
			1)自定义类MyThread继承Thread类
			2)MyThread类里面重写run()
				run+alt+/
				为什么?
					不是类中所有代码都需要被线程执行(方法包含 需要线程执行的代码(比较耗时的代码)),为了区分哪些代码能够被线程执行。
				getName();	//获取线程名称(在run()方法中)
				Thread.currentThread().getName();	//通用获取线程名称
			3)创建对象
				MyThread mt = new MyThread();
			4)启动线程
				mt.start();
		注意:重复调用run方法是单线程
				run()和start()的区别?
					run():仅仅是封装被线程执行的代码,直接调用是普通方法
					start():首先启动了线程,然后再由jvm去调用该线程的方法
			  IllegalThreadStasteException:指非法线程状态异常
				why?
					两个start()相当于是mt线程被调用了两次。而不是两个线程启动。
					解决:创建两个线程对象
					MyThread mt2 = new MyThread();
					mt.setName("baron");	//设置线程名称
					mt.start();
					mt2.start();
		B:实现Runnable接口(常用)
			1)自定义类MyRunnable类实现Runnable接口
			2)重写run()方法
			3)创建MyRunnable类对象
			4)创建Thread类对象,并把3)步骤的对象作为构造参数传递
		C:有了方式一为什么还有方式二?
			解决了Java单继承带来的局限性
			适合多个相同程序的代码去处理一个资源的情况,把线程同程序的代码,数据有分离。较好的体现了面向对象的设计思想。
	4、线程的调度和优先级问题
                假如我们的计算机只有一个 CPU,那么 CPU 在某一个时刻只能执行一条指令,线程只 有得到 CPU时间片,也就是使用权,才可以执行指令。
		A:线程的两种调度模型
			a:分时调度:所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间片
			b:抢占式调度 (Java采用的是该调度方式):优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个,优先级高的线程获取的 CPU 时间片相对多一些。
		B:获取和设置线程优先级
			a:默认是5
			b:范围是1-10
			c:获取线程对象优先级
				public final int getPriority()
					mt.getPriority();
			d:设置对象优先级
					mt.setPriority();
				IllegalArgumentException:非法参数异常
				线程优先级高仅仅表示线程获取的CPU时间片的几率高,但要在次数比较多,或者多次运行的时候才能看到比较好的效果
	5、线程的控制(常见方法)
		A:休眠线程
			public static void sleep(long millis)
				Thread.sleep(1000);	//在run()或main()方法中休息一秒
		B:加入线程
			public final void join()	//等待线程终止(意思是其它线程等待我执行完毕后才可执行)
				mt.join();
		C:礼让线程
			public static void yield():暂停当前正在执行的线程对象,并执行其它线程。
				Thread.yield();	//在run()方法中让多个线程的执行更加和谐,但不能靠它保证一人一次。
		D:后台线程
			public final void setDaemon(boolean on):将该线程标记为守护线程或用户线程,当正在运行的线程是守护线程时,Java虚拟机退出,该方法必须在启动线程前调用。
				mt.setDaemon(true);
				mt2.setDaemon(true);
		E:终止线程(掌握)
			public final void stop():过时,但是还可以用
				mt.stop();
			public void interrupt():终止线程,把线程状态终止,并抛出InterruptedException
			mt.interrupt();
	6、线程的生命周期(参照	线程生命周期图解.bmp)
		A:新建:创建线程对象
		B:就绪:有执行资格,无执行权限
		C:运行:有执行资格,有执行权限
		D:阻塞:由于一些操作让线程处于该状态,没有执行资格,没有执行权限。一些操作可将其激活,激活后处于就绪状态。
		E:死亡:线程对象变成垃圾,等待被回收
	7、电影院卖票程序的实现
                某电影院目前正在上映贺岁大片,共有100张票,而它有3个售票窗口售票,请设计一个程序模拟该电影院售票。
		A:继承Thread类
		B:实现Runnable接口
	8、电影院卖票程序出问题
		A:为了更符合真实的场景,加入了休眠100毫秒。
		B:卖票问题
			a:同票多次
			b:负数票
	9、多线程安全问题的原因(也是我们以后判断一个程序是否有线程安全问题的依据)
		A:是否有多线程环境
		B:是否有共享数据
		C:是否有多条语句操作共享数据
	10、同步解决线程安全问题
		A:同步代码块
			synchronized(对象) {
				需要被同步的代码;
			}
			
			这里的锁对象可以是任意对象。
			
		B:同步方法
			把同步加在方法上。
			
			这里的锁对象是this
			
		C:静态同步方法
			把同步加在方法上。
			
			这里的锁对象是当前类的字节码文件对象(反射再讲字节码文件对象)
			
			例子:
				@Override
					public void run() {
						while (true) {
							if(x%2==0){
								synchronized (SellTicket.class) {	//例子B换成this
									if (tickets > 0) {
										try {
											Thread.sleep(100);
										} catch (InterruptedException e) {
											e.printStackTrace();
										}
										System.out.println(Thread.currentThread().getName()
												+ "正在出售第" + (tickets--) + "张票 ");
									}
								}
							}else {
					
								sellTicket();
						
							}
							x++;
						}
					}
					
					private static synchronized void sellTicket() {
						if (tickets > 0) {
						try {
								Thread.sleep(100);
						} catch (InterruptedException e) {
								e.printStackTrace();
						}
						System.out.println(Thread.currentThread().getName()
									+ "正在出售第" + (tickets--) + "张票 ");
						}
				}
				}
		D:同步的前提
			多个线程
			多个线程使用的是同一个锁对象
			
		E:同步的弊端:
			当线程较多时,因为每个线程都会去判断同步上的锁,很耗资源,无形中降低程序运行效率
	11、回顾以前的线程安全的类
		A:StringBuffer
		B:Vector
		C:Hashtable
		D:如何把一个线程不安全的集合类变成一个线程安全的集合类
			用Collections工具类的方法即可。
			// Vector是线程安全的时候才去考虑使用的,但是我还说过即使要安全,我也不用你
			// 那么到底用谁呢?
			// public static  XXXX synchronizedXXXX(XXXX XXXX)
			List list1 = new ArrayList();// 线程不安全
			List list2 = Collections.synchronizedList(new ArrayList()); // 线程安全
posted @ 2017-10-17 20:37  wangw0107  阅读(135)  评论(0编辑  收藏  举报