java基础总结下Word格式.docx
《java基础总结下Word格式.docx》由会员分享,可在线阅读,更多相关《java基础总结下Word格式.docx(34页珍藏版)》请在冰豆网上搜索。
同一个操作系统中执行的多个并行的子程序。
可以提高cpu的使用率
线程:
在同一个进程当中执行的子程序流
多线程:
同一个进程当中并发执行的多个子程序流。
进程与线程的区别:
进程有独立的进程空间,进程中的数据存放空间(堆空间和栈空间)是独立的。
线程的堆空间是共享的,栈空间是独立的,线程消耗的资源也比进程小,相互之间可以影响的。
java中如何调进程:
调用本地程序的两个类
Runtime
Runtime.getRuntime.exec(...);
//执行一个程序
其返回值就是Process类型
Process
注意:
只有运行状态的线程才有机会执行代码,主线程的中止不会影响其他的正在运行中的线程,主线程中止也就是main()方法退出了。
只有进程中的所有线程都中止时,进程(JVM进程)才会退出,只要有线程没有中止,进程就不会退出。
操作系统决定线程是否有优先级,独占式的操作系统中系统会有优先级的概念,共享式的操作系统则不会有优先级的。
在线程的内部,程序依然顺序执行
线程编程的两种方法:
写一个类,继承Thread类,覆盖Thread类中继承来的run()方法,这样就写好了自定义的线程类。
继承java.lang.Thread类:
classMyThreadextendsThread{
publicvoidrun(){//覆盖run(),线程体方法,自身其实就是普通的方法
.......
}
}
启动线程:
publicclassTestThread{
publicstaticvoidmain(){
Threadt1=newMythread();
T1.start();
//调用start()来启动线程,线程启动方法,向线程调度器说明当前线程已经准备好了,是一种可运行状态
写一个类,实现Runable接口,实现其中的run()方法。
这种方法写好的类的对象需要作为线程类创建对象时构造方法的参数。
实现java.lang.Runnable接口:
ClassMyThreadimplementsRunnable{
publicvoidrun(){
RunnablemyThread=newMyThread();
Threadt=newThread(myThread);
t.start();
Thread中的一些方法:
currentThread()
返回对当前正在执行的线程对象的引用(实现接口方式时使用)
sleep(longmillis)
在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)。
本线程不会去抢,除非sleep结束。
多个线程之间都会去抢执行权限,不会考虑优先级。
yield()
暂停当前正在执行的线程对象,并执行其他线程。
只给本类或者优先级大于本类优先级的线程去抢。
join()
等待该线程终止。
放在start()前面则没有用处。
setDaemon(booleanon)
将该线程标记为守护线程,守护线程需要依赖其他线程,会在虚拟机停止的时候停止。
线程的生命周期:
1)初始状态:
此时线程只是处于JVM进程中,只是创建了一个线程对象,并没有真正开始运行。
2)可动行状态:
调用线程对象的start()方法,此时线程才真正的被创建,进入可运行状态,等待CPU的调度。
“万事俱备,只欠CPU”。
3)运行状态:
正在运行的线程,此时它拥有CPU的执行权。
4)阻塞状态:
运行状态中的线程,如果正在等待用户输入或调用了sleep()和join()等方法都会导致线程进入阻塞状态,注意从阻塞状态出来的线程不一定马上回到运行状态,而是重新回到可运行状态,等待CPU的再次调度。
5)等待队列状态:
一个线程调用一个对象的wait()会自动放弃该对象的锁标记,进入等待队列状态,只有当有另外一线程调用临界资源的notify()或notifyAll()方法,建议多使用notifyAll(),才会将等待队列中的线程释放,此线程进入锁池状态。
6)锁池状态:
每个对象都有互斥锁标记,以防止对临界资源的访问造成数据的不一致,和数据的不完整性。
一个线程拥有一个对象的锁标记后,另一线程想访问该对象,必须在锁池中等待。
由系统决定哪个线程拿到锁标记并运行。
注意从锁池状态出来的线程不是马上回到运行状态,而是重新回到可运行状态,等待CPU的再次调度。
7)终止状态:
一个线程运行结束后称为终止状态,一个进程中只有所有的线程退出后才会终止。
多线程的同步:
多线程并发访问同一个对象(临界资源),如果不对线程进行同步控制,破坏了原子操作(不可再分的操作),则会造成临界资源(两个线程同时访问的资源)的数据不一致。
每一个对象都有一个互斥的锁标记和一个锁池。
当线程拥有这个对象的锁标记时才能访问这个资源,没有锁标记便进入锁池,保证在同步代码块中只有一个线程,解决了多线程同步控制的问题。
关键字:
synchronized//线程在同步代码中必须采用串行访问
synchronized修饰代码块:
对括号内的对象object加锁,只有拿到对象锁标记的线程才能进入该代码块。
publicvoidpush(charc){
synchronized(object){//object只要是对象就可以,但必须保证是同一对象
……
同步代码
}
synchronized修饰方法:
在整个方法范围内对当前对象的加锁,只有拿到对象锁标记的线程才能执行该方法。
尽可能的少用
publicsynchronizedvoidpush(charc){
……
一个线程可以同时拥有多个对象的锁标记,锁标记如果过多,就会出现线程等待其他线程释放锁标记,而又都不释放自己的锁标记供其他线程运行的状况,造成死锁。
静态方法可以是同步方法:
但是它所锁的并不是当前对象,是类对象。
抽象方法不能是synchronized同步的方法。
构造方法不能是synchronized同步的方法。
线程因为未拿到锁标记而发生阻塞进入锁池(lockpool)。
每个对象都有自己的一个锁池的空间,用于放置等待运行的线程。
由系统决定哪个线程拿到锁标记并运行
利用Collections类中的synchronizedXxxx(Xxxxss)方法可以得到相应集合的线程安全的集合
在同步语句块中不能直接操作对象锁正在使用的对象。
对象与锁一一对应。
同步依赖对象锁,锁对象相同,同步语句串行,锁对象不同,同步语句并行。
顺序锁,不要回调,反向打开。
能不用同步就不用同步,有数据共享冲突时才使用同步。
等待通知机制:
线程间通信使用的空间称之为对象的等待对列(waitpool),该队列也是属于对象的空间的。
使用Object类中wait()的方法,在运行状态中,线程调用wait(),此时表示线程将释放自己所有的锁标记和CPU的占用,同时进入这个对象的等待池。
等待池的状态也是阻塞状态,只不过线程释放自己的锁标记。
只有在对该对象加锁的同步代码块里,才能掉用该对象的wait(),表示线程将会释放所有锁标记,进入等待队列,线程将进入等待队列状态。
一个线程进入了一个对对象加锁的同步代码块,并对该对象调用了wait()方法,释放自己拥有的所有锁标记,进入该对象等待队列,另一个线程获得了该对象的锁标记,进入代码块对该对象调用了notify()方法,就会从等待队列里释放出一线程,释放出的这个线程要继续运行就还要进入那个同步代码块,因为得不到要访问代码块对象的锁标记,而进入该对象的锁池,等待锁标记释放。
什么情况下释放锁:
同类代码执行完毕。
异常未处理,错误退出。
调用wait()。
相关方法:
1)wait():
交出锁和CPU的占用;
2)notify():
将从对象的等待池中移走一个任意的线程,并放到锁池中,那里的对象一直在等待,直到可以获得对象的锁标记。
3)notifyAll():
将从等待池中移走所有等待那个对象的线程并放到锁池中,只有锁池中的线程能获取对象的锁标记,锁标记允许线程从上次因调用wait()而中断的地方开始继续运行
用notifyAll()取代notify(),因为在调用notify()方法时,是由系统决定释放出哪个线程。
只能对加锁的资源进行wait()和notify()。
判断是否进行等待wait()时,用while代替if来进行判断。
I/O流
字节输入流:
InputStream类为所有字节输入流的父类
三个基本的read()方法:
intread()
从流里读出的一个字节。
不推荐使用
intread(byte[]b)
将数据读入到字节数组中,并返回所读的字节数
intread(byte[]b,intoff,intlen)
off从哪里开始读。
len读取多少。
将输入流中最多len个数据字节读入字节数组。
其它方法:
voidclose()
关闭此输入流并释放与该流关联的所有系统资源。
intavailable()
返回不受阻塞地从此输入流读取的字节数。
longskip(longn)
跳过和放弃此输入流中的n个数据字节,该方法有可能失效。
booleanmarkSupported()
测试此输入流是否支持mark和reset方法。
voidmark(intn)
在此输入流中标记当前的位置
voidreset()
将此流重新定位到对此输入流最后调用mark方法时的位置。
字节输出流:
OutputStream类是所有字节输入流的父类
三个基本的write()方法:
voidwrite(intn)
将指定的字节写入此输出流。
voidwrite(byte[]b)
将b.length个字节从指定的字节数组写入此输出流。
voidwrite(byte[]b,intoff,intlen)
将指定字节数组中从偏移量off开始的len个字节写入此输出流。
voidclose()
关闭此输出流并释放与此流有关的所有系统资源。
voidflush()
刷新此输出流并强制写出所有缓冲的输出字节。
文件输入输出流:
FileInputStream和FileOutputStream
要构造一个FileInputStream,所关联的文件必须存在而且是可读的。
如:
FileInputStreamfis=newFileInputStream("
myfile.dat"
);
要构造一个FileOutputStream,而输出文件已经存在,则它将被覆盖。
FIleOutputStreamfos=newFileOutputStream("
results.dat"
要想以追加的方式写,则需要一个额外的参数,如:
FileOutputStreamoutfile=newFileOutputStream("
true);
//参数为true时输出为追加,为false时为覆盖。
流的概念:
程序与数据来源之间的桥梁
流的分类:
按数据方向分:
输入流和输出流
输入流:
InputStream/Reader
OutputStream/Writer
按数据类型分:
字节流和字符流
字节流:
InputStream/OutputStream
字符流:
Reader/Writer
按流的功能分:
节点流和处理流
节点流用操作数据的来源。
处理流用来封装节点流,从而给节点流增加一个功能,不能独立存在,在关闭流时如果使用了处理流,只需关闭最外层的流就可以了。
区分节点流和处理流的小方法:
看构造器,节点流参数为数据来源,而处理流参数为其他流。
选择流的思路:
先考虑是输入流还是输出流,
再考虑是字节流还是字符流,
最后考虑是节点流还是处理流。
字符流:
Reader和Writer所有字符流的父类型
Java技术使用Unicode来表示字符串和字符,而且提供16位版本的流,以便用类似的方法处理字符。
如果构造了一个连接到流的Reader和Writer,转换规则会在使用缺省平台所定义的字节编码和Unicode之间切换。
桥梁流:
InputStreamReader和OutputStreamWriter(字节流转化成字符流的桥转换器)
这两个类不是用于直接输入输出的,他是将字节流转换成字符流的桥转换器,并可以指定编解码方式。
逐行读写流:
BufferedReader/BufferedWriter
以上两个都是过滤流,需要用其他的节点流来作参数构造对象。
BufferedReader的方法:
readLine():
String,当他的返回值是null时,就表示读取完毕了。
要注意,再写入时要注意写换行符,否则会出现阻塞。
BufferedWriter的方法:
newLine(),这个方法会写出一个换行符。
管道流:
线程交互的时候使用
PipedInputStream/PipedOutputStream
传送输出流可以连接到传送输入流,以创建通信管道。
传送输出流是管道的发送端。
通常,数据由某个线程写入PipedOutputStream对象,并由其他线程从连接的PipedInputStream读取。
管道输出流和管道输入流需要对接。
数据流:
DataInputStream和DataOutputStream
通过流来读写Java基本类,注意DataInputStream和DataOutputStream的方法是成对的。
支持直接输出输入各种数据类型。
使用DataOutputStream/DataInputStream时,要注意写入顺序和读取顺序相同,否则会将没有分割写入的信息分割不正确而读取出错误的数据。
Properties类:
针对属性文件(*.properties,内容是name=value)进行操作,在java.util包下
load(InputStreaminStream)
从输入流中读取属性列表(键和元素对)。
getProperty(Stringkey)
用指定的键在此属性列表中搜索属性。
java编码方式:
编码:
把字符转换成数字存储到计算机中,按ASCII将字母映射为整数。
解码:
把数字从计算机转换成相应的字符的过程。
不同的国家有不同的编码,当编码方式和解码方式不统一时,产生乱码。
因为美国最早发展软件,所以每种的编码都向上兼容ASCII所以英文没有乱码。
ASCII(英文)1个字符占一个字节(所有的编码集都兼容ASCII)
ISO8859-1(拉丁文)1个字符占一个字节
GB-2312/GBK1个字符占两个字节(多用于中文)
Unicode1个字符占两个字节(网络传输速度慢)
UTF-8变长字节,对于英文一个字节,对于汉字两个或三个字节。
中文编码时出现乱码的情况:
用流操作文件。
网页(动态静态)。
网络传递消息。
解决乱码的方式:
Stringtemp=乱码的字符串
temp=newString(temp.getBytes("
ISO8859-1"
),"
GBK"
)
将temp按照ISO8859-1的方式进行解码生成一个字节序列,然后在按照GBK的方式解码字节序列生成字符串。
File类:
可表示文件或者目录
File下的方法是对磁盘上的文件进行磁盘操作,但是无法读写文件的内容。
构造器:
File(Stringpathname)//以文件的路径做参数
File类的方法:
booleancreateNewFile()
创建一个新文件
FilecreateTempFile(Stringprefix,Stringsuffix,Filedirectory)
在指定目录中创建一个新的空文件,使用给定的前缀和后缀字符串生成其名称。
会在前缀和后缀之间加一个随机数
booleanmkdir()
创建一个新目录
booleandelete()
删除文件,删除的是创建File对象时指定与之关联创建的那个文件。
String[]List()
返回当前File对象下所有显文件和目录名(相对路径)
File[]ListFiles()
返回当前File对象(必须是目录)下的所有File对象,可以用getName()来访问到文件名。
booleanisDirectory()和booleanisFile()
判断究竟是目录还是文件。
booleanexists()
判断文件或文件夹是否存在。
StringgetPath()
获得相对路径。
StringgetAbsolutePath()
获得文件的绝对路径
File类的对象实施表示一个文件并不是真正的文件,只是一个代理而已,通过这个代理来操作文件
创建一个文件对象和创建一个文件在java中是两个不同的概念。
前者是在虚拟机中创建了一个文件,但却并没有将它真正地创建到OS的文件系统中,随着虚拟机的关闭,这个创建的对象也就消失了。
而创建一个文件才是在系统中真正地建立一个文件。
例如:
Filef=newFile(“11.txt”);
//创建一个名为11.txt的文件对象
f.CreateNewFile();
//真正地创建文件
RandomAccessFile:
允许随机访问文件,类支持直接输出输入各种数据类型。
RandomAccessFile(Filefile,Stringmode)
创建从中读取和向其中写入(可选)的随机存取文件流,该文件由File参数指定。
RandomAccessFile(Stringname,Stringmode)
创建从中读取和向其中写入(可选)的随机存取文件流,该文件具有指定名称。
mode(r:
以只读方式打开rw:
可读可写,不存在则创建)
longgetFilePointer()
返回文件指针的当前位置。
voidseek(longpos)
设置文件指针到给定的绝对位置。
longlength()
返回文件的长度。
对象流:
ObjectInputStream和ObjectOutputStream(实现对象序列化)
对象流是过滤流,需要节点流作参数来构造对象,用于直接把对象写入文件和从文件中读取对象。
只有实现了Serializable接口的类型的对象才可以被读写,Serializable接口是个标记接口,其中没有定义方法。
对象会序列化成一个二进制代码,文件中保存对象的属性。
writeObject(o)、readObject()这两个是对象读写操作时用的方法。
Objecto=newObject();
FileOutputStreamfos=newFileOutputStream("
Object.txt"
ObjectOutputStreamoos=newO