Java核心组件部分知识点.docx
《Java核心组件部分知识点.docx》由会员分享,可在线阅读,更多相关《Java核心组件部分知识点.docx(16页珍藏版)》请在冰豆网上搜索。
Java核心组件部分知识点
Java课程
Phase3
目录
Java课程1
Phase31
2016-06-022
Android中的多线程应用2
往期回顾2
线程基础2
线程对象的创建3
线程对象的状态及常用方法3
线程同步4
关于内部类的问题4
2016-06-037
线程通讯->线程同步协作7
线程通讯应用-前提/实现7
单例模式7
回顾->静态修饰符详解static8
2016-06-069
FAQ?
9
Android线程通讯的消息模型9
消息对象的伪代码实现9
Android中线程通讯的实现–借助消息模型10
线程消息模型FAQ10
Android中的HandlerThread{}类10
2016-06-0710
往期回顾:
android中的线程应用机制?
线程通讯机制?
消息模型架构?
10
线程方法应用介绍11
异步任务AsyncTask11
2016-06-02
Android中的多线程应用
往期回顾
1.Android数据存储
a)内存
b)外存(内置sdcard,外置sdcard,网络)
2.AndroidUI操作
a)UI是系统(App)对外的窗口
b)UI负责与用户进行交互
所有的UI操作以及事件处理操作都应该放在主线程执行;
所有的耗时操作都应该在子线程操作;
3.Android中的线程应
常用的线程操作模式:
工作线程进行耗时操作,操作数据,并将操作完成的数据结果传递给主线程,由主线程更新UI。
FAQ?
a)何为线程?
b)何为工作线程?
何为主线程?
c)工作线程如何将数据传递给主线程?
->线程通讯!
!
线程基础
何为操作系统?
a)操作系统是软件;
b)作用为负责管理和调度硬件,并为应用软件的执行提供平台支持;
操作系统分为单任务、多任务操作系统:
单任务操作系统:
DOS;->同一时刻只能执行一个任务
多任务操作系统:
Windows,Linux,Unix,IOS;->同一时刻可执行多个任务;
Android底层系统是Linux.
所谓多任务即同一时刻可执行多个任务,即能够并发执行多个任务,但多个任务是否能够同时执行仍取决于CPU的个数即核数。
对于单CPU而言,仅有一个处理器轮询多个任务,但轮询时间极短,宏观上看上去感觉像是多个任务(即应用程序)同时进行,但实际上每个时间片段仅执行一个任务。
何为进程?
正在运行的程序都是进程;Windows平台下进程表现为”.exe”程序;(没有运行的程序不是进程);操作系统中所有的任务都是运行在其对应的进程中的;进程由操作系统进行创建、启动并管理;操作系统在启动进程时率先启动一个主线程(即主任务);主线程负责执行任务,主线程中可以调用其他的任务(即子线程)。
此处,进程即为应用程序,线程为应用程序中的任务,可有多个,但仅有一个主线程,其他的均为子线程。
何为线程?
线程是进程中的一个顺序执行流(即一个线程内的所有操作都是顺序执行的),一个进程可以有多个线程,其中肯定有一个是主线程,主线程之外的其他线程通称为工作线程(子线程);
Java中所有的线程类型为Thread类型。
线程对象的创建
Java中的线程对象的创建需要借助Thread{}类,构造方法如下:
a)Thread()->需要重写Thread{}类的run()方法,在此方法中执行业务代码。
b)Thread(Runnabletask)->重写实现了Runnable{}接口中的run()方法;在此方法中执行业务逻辑;
线程的启动通过调用线程对象的start()方法来实现。
多线程并发执行,可以提高系统的处理效率,同时也会增加系统的维护和调试难度。
线程对象的状态及常用方法
1.新建状态(newThread())
2.就绪状态(线程处于可运行状态,可以获得CPU的资源(但能否获得CPU资源仍需由CPU属性及当前状态决定))
3.运行状态(正在执行线程的run()方法)
4.阻塞状态(例如调用了sleep(longtimeMillisecond)方法,或者执行IO操作);如:
scanner.nextLine();
5.死亡状态(线程运行结束后被销毁的状态,destroy()方法)
6.常用方法start;run;sleep;interrupt;setDaemon;join;yield;getName;setName;currentThread;isAlive;
setDaemon(trueorfalse)设置当前线程是否为守护线程(当进程中无任何线程执行时,该线程终止);
join(longtimeMillis)设定某一线程优先执行;设定时间参数表示让该线程优先执行一段时间后,继续之后后面的代码;若不设定时间,则指仅当该线程执行完成后,方可执行后面的代码;
yield()让出cpu,但线程仍处于就绪状态;
线程同步
定义:
多个线程并发执行时,在共享数据集上的互斥与协作。
线程同步时保证线程安全的手段。
例如多个线程同时售卖共同的100张票;
使用synchronized关键字,保证在某一时刻只能有一个线程在此代码块上执行。
多个线程在当前代码块按顺序执行。
方法一:
使用同步代码块,即在run()方法中,将共同使用的数据使用synchronized(对象锁){执行代码,内含共同使用的数据}修饰;此处“对象锁”可以使用this,非静态类中表示该类的对象,如果该类为静态类,则表示该静态类所在的类的对象(***.class);
方法二:
使用同步方法,即publicsynchronizedvoidmethod(){执行代码块,内含共同使用的数据};
回顾:
StringBuffer是线程安全的StringBuilder,前者使用线程同步方法,但效率较低,所以区分使用。
详见源码的append()方法。
Vector是线程安全的ArrayList.
HashTable是线程安全的HashMap.Put()方法
Collection中有synchronizedSet等
接口List,Set,Queue
Map
HashMap,TreeMap,LinkedHashMap
关于内部类的问题
Java程序中创建成员内部类对象时,当该成员内部类为非static变量,需要先创建外部类的对象,然后通过外部类的对象.new关键字来创建内部类的对象;
而在Android应用程序中,可在onCreate()方法分中直接new出非静态的成员内部类的对象:
如InnerThreadinner=newInnerThread();
为什么呢?
因为Java中main方法是static方法,静态方法只能调用静态变量,否则就必须创建外部类的对象以后(此时已经作为外部类对象的属性加载了内部类),方可创建内部类的对象。
在android的activity的onCreate()方法中,该方法为非static方法,所以可直接new出内部类的对象,因为onCreate()方法实际上就是创建了一个该activity类的对象,此时已经将内部类加载到内存中,所以可以直接new内部类的对象。
代码如下:
publicclassThreadPractice{
protectedstaticStrings;
publicstaticvoidmain(String[]args){
finalScannersc=newScanner(System.in);
newThread(){
@Override
publicvoidrun(){
System.out.print("请输入:
");
s=sc.nextLine();
sc.close();
}
}.start();
/*
*线程对象start()方法执行后,默认执行线程对象的run()方法;
*该run()方法中明示:
当线程对象参数中的Runnable接口的实现类对象target不为空时,
*执行target对象的run()方法,所以可通过传入target参数实现对应的功能。
*该target对象的run()方法可以执行的先决条件是Thread类对象的run()方法中有调用,
*即,如果重写了Thread类的run()方法,但重写的方法中未调用target的run()方法,
*则永远不会执行target对象的run()方法。
*/
while(s==null)
;
newThread(newRunnable(){
@Override
publicvoidrun(){
System.out.println("s="+s);
}
}).start();
Runnablerunner=newRunnable(){
@Override
publicvoidrun(){
//此处代码输出
System.out.println("Runnable{}->runner.run()");
}
};
/*
*成员内部类的对象的创建在main()方法中:
该方法为静态方法
*当成员内部类为非static时,只有当创建了外部类的对象后,才可以通过外部类的对象,
*使用.new关键字,创建内部类的对象;因为只有创建了外部类的对象后,内部类才会像外部类的其他成员(privateint
*x)一样被加载到内存,此时才会有内部类出现。
*
*当成员内部类为static时,即该类加载时先将static关键字标识的成员全部加载到内存中,所以此时可以直接创建静态内部类的对象。
*/
ThreadPracticepractice=newThreadPractice();
InnerThread1inner=practice.newInnerThread1(runner);
//InnerThreadinner=newInnerThread(runner);
/*
*创建内部类的对象并使用传入参数runner的构造方法;
*如果重写了InnerThread中的run()方法,且其中不调用runner的run()方法;
*则runner的run()方法永远不会执行;
*当不重写InnerThread类中的run()方法时,其对象默认调用父类Thread{}的run()方法;
*在该父类的方法中有调用runner的run()方法的代码,所以不重写时,会调用runner的run()方法。
*/
inner.start();
classInnerThread2extendsThread{
publicInnerThread2(){
super();
}
publicInnerThread2(Runnablerunnable){
super(runnable);
}
@Override
publicvoidrun(){
//此处代码输出
System.out.println("InnerThread2->Override->run()");
}
}
/*
*此处InnerThread2{}为局部内部类,即定义在方法中,代码按照顺序执行,
*所以若要创建该类的对象,则必须在该类的声明代码以后执行创建代码。
*执行过程为ThreadPractice{}类加载成员属性,加载main方法,main方法中依次执行对应的代码。
*/
InnerThread2inner2=newInnerThread2(runner);
inner2.start();
}
voidtest(){
/*
*在非main()方法中,或其他任意非static方法中,均可直接创建内部类的对象;因为非静态方法的调用,必须由外部类的对象进行调用,
*即创建了外部类的对象(此时会加载内部类到内存中)以后,可任意调用该test()方法,在本方法中创建内部类的对象。
*此种情况即是android应用程序中activity的onCreate()方法创建内部类对象的情况。
*/
InnerThread1in=newInnerThread1();
in.start();
}
classInnerThread1extendsThread{
publicInnerThread1(){
super();
}
publicInnerThread1(Runnablerunnable){
super(runnable);
}
//@Override
//publicvoidrun(){
////此处代码输出
//System.out.println("InnerThread1->Override->run()");
//}
}
}
2016-06-03
线程通讯->线程同步协作
定义:
多个线程并发执行时,实现线程之间的交互。
即互斥的线程之间通讯。
借助Object类的wait(),notify(),notifyAll()方法。
线程通讯应用-前提/实现
a)有共享数据集;
b)多线程之间互斥(同步代码块or同步方法)->对共享数据集加锁;
c)执行对象锁的通讯方法(wait(),notify(),notifyAll());
Note:
调用这些通讯方法时,使用创建synchronized代码块或方法时候的对象锁来调用。
单例模式
定义:
单例模式是设计模式中的一种设计方法;
主要用于设计对象的创建问题,如何创建?
如何获得?
类的外部不能直接创建该类对象,但可通过该类的静态方法获得对象,且获得的对象有且只有一个。
单例模式应用场景举例:
a)Windows任务管理器;
b)字符串池;常量池;
c)系统日志;
单例模式的实现:
a)构造方法私有化;
b)类内部创建对象;
c)提供静态方法返回实例;
1)静态初始化类对象,静态方法直接返回。
线程安全、效率高但占用内存空间。
使用场景:
小对象,经常用的对象;
2)静态方法中判断是否为null,依据结果创建对象,并返回对象。
如果单线程访问,不考虑线程同步的安全问题;多线程访问,则需要使用synchronized关键字修饰该静态方法,保证线程安全。
但节省内存空间。
使用场景:
大对象,不常用的对象;
3)线程内部单例
在每个线程内部,某个类的对象在某一时刻只能有一个。
实现思想:
当对象创建以后,可以将对象绑定到当前线程上。
具体实现:
借助ThreadLocal{}类,此类中提供set()方法能够将对象绑定到当前线程,也可以通过get()方法从当前线程获取对象。
Note:
方法1)为饿汉式单例模式,2)为懒汉式单例模式3)线程内部单例模式。
回顾->静态修饰符详解static
Static修饰符
a)修饰内部类(不能修饰外部类);
b)修饰属性(field)(类的内部,方法外部的变量),而不是变量,变量包含全部变量和局部变量,所以只能修饰全局变量;
c)修饰方法;
类加载时,即将类读到内存过程中(编译),顺序执行:
1)在代码区,分配类存储空间;
2)按照代码撰写顺序初始化类变量,执行静态代码块;
3)执行main方法
2016-06-06
FAQ?
1.Android中工作主线程获得数据以后如何传递给主线程?
Ex:
工作线程通过网络下载图片,通过主线程将图片更新到页面上。
下载为耗时操作,子线程无法更新UI。
2.Android中主线程的数据如何传递给工作线程?
例如:
主线程将要下载的文件名称传递给工作线程,由工作线程执行耗时操作。
Android线程通讯的消息模型
作用:
线程之间进行数据传递。
借助以下对象:
1)Message{}消息对象:
数据的载体
2)MessageQueue{}–消息队列:
存储多个消息对象
3)Looper{}–迭代器对象:
迭代消息队列
4)Handler{}-消息处理对象:
发送、处理消息数据
消息对象的伪代码实现
classMessage{
Objectobj;//借助该属性存储数据,因数据类型未知,固使用Object对象
}
classMessageQueue{//FIFO
LinkedListlist=newLinkedList();//存储消息对象的队列
}
classLooper{//迭代队列,需要传入消息队列
MessageQueuemq;//存储Message对象集合,即想要传递的数据集合
publicvoidloop(){
//循环迭代消息队列
}
publicvoidexit(){
//退出循环
}
}
ClassHandler{//迭代队列后处理消息(发送、处理)
PublicvoidsendMessage(Messagemsg){}
PublicvoidhandleMessage(Messagemsg){}
}
Android中线程通讯的实现–借助消息模型
1.工作线程->主线程
关键点:
工作线程中获得与主线程相关联的Looper对象,主线程默认存在Looper对象,可使用getMainLooper()获得;
2.主线程->工作线程
主线程获得与工作线程关联的Looper对象,但子线程默认没有Looper对象,如何获得?
自己创建。
Looper构造方法为私有!
通过调用Looper.prepare()&Looper.myLooper()方法获得子线程的Looper对象。
注意,获得looper后要执行loop()方法,即循环遍历消息队列MessageQueue,检索是否有消息存在,有则读取。
创建handler时,需要重写其handleMessage()方法,执行消息处理的代码。
线程消息模型FAQ
1.一个线程有几个looper?
一个;
2.一个线程有几个MessageQueue?
一个;
3.MessageQueue何时创建?
looper创建时创建;
4.一个线程可以有多个Handler对象吗?
可以,谁负责发送,谁负责处理消息;但一般只使用一个handler足矣。
Note:
给哪个线程发消息,就构建或获取与该线程相关联的looper,然后以该looper作为参数创建handler对象。
一个类可以有很多方法,但具体每个方法运行在哪个线程,取决于由哪个线程调用了此方法,即谁调用,运行在谁处。
如:
handleMessage方法运行在哪个线程?
取决于looper在哪个线程,因由looper调用handleMessage方法。
Android中的HandlerThread{}类
此类为线程类,启动时默认创建looper对象,可通过该对象的getLooper()方法获取该类的looper,该类底层已完成线程同步,所以不需考虑线程安全问题。
2016-06-07
往期回顾:
android中的线程应用机制?
线程通讯机制?
消息模型架构?
应用机制:
子线程执行耗时操作;
通讯机制:
借助消息的传递,目的在于避免主线程被阻塞,影响用户体验。
消息模型架构:
a)Message
b)MessageQueue
c)Looper
d)Handler
线程方法应用介绍
Handler.postDelayed(Runnablerunner,longtimeMillis);//延时发现消息
Handler.post();//立即发送
异步任务AsyncTask
Android中模板方法模式的应用
定义:
设计模式中的一种行为模式->对象行为模式;
模板方法模式依托继承机制,实现代码的复用。
核心思想:
a)将代码中不变部分写到父类中;
b)将代码中可变部分交给子类实现;
模板方法构成分析:
a)父类:
抽象类(通常),具体类;
b)子类:
具体类
父类中方法构成:
1)模板方法->具体方法,不能被重写
2)基本方法->具体方法,抽象方法,钩子方法
钩子方法:
hookmethod;