单元8 输入输出流与多线程
任务8.1 使用字节流设计记事本
8.1 输入输出流概述
8.2 文件概述 File myFilePath = new File_(folderPath)_;
//目录新建 new File(folderPath) 建立文件目录对象 根据路径
File myFilePath = new File_(folderPath)_;
File 构造方法
构造器 | 描述 |
---|---|
File | |
(File | |
parent, String | |
child) | 从父抽象路径名和子路径名字符串创建新的 File实例。 |
File | |
(String | |
pathname) | 通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。 |
File | |
(String | |
parent, String | |
child) | 从父路径名字符串和子路径名字符串创建新的 File实例。 |
File | |
(URI | |
uri) | 通过将给定的 file: URI转换为抽象路径名来创建新的 File实例。 |
File 方法摘要
变量和类型 | 方法 | 描述 |
---|---|---|
boolean | canExecute | |
() | 测试应用程序是否可以执行此抽象路径名表示的文件。 | |
boolean | canRead | |
() | 测试应用程序是否可以读取此抽象路径名表示的文件。 | |
boolean | canWrite | |
() | 测试应用程序是否可以修改此抽象路径名表示的文件。 | |
int | compareTo | |
(File | ||
pathname) | 按字典顺序比较两个抽象路径名。 | |
boolean | createNewFile | |
() | 当且仅当具有此名称的文件尚不存在时,以原子方式创建由此抽象路径名命名的新空文件。 | |
static File | createTempFile | |
(String | ||
prefix, String | ||
suffix) | 在默认临时文件目录中创建一个空文件,使用给定的前缀和后缀生成其名称。 | |
static File | createTempFile | |
(String | ||
prefix, String | ||
suffix, File | ||
directory) | 在指定目录中创建一个新的空文件,使用给定的前缀和后缀字符串生成其名称。 | |
boolean | delete | |
() | 删除此抽象路径名表示的文件或目录。 | |
void | deleteOnExit | |
() | 请求在虚拟机终止时删除此抽象路径名表示的文件或目录。 | |
boolean | equals | |
(Object | ||
obj) | 测试此抽象路径名与给定对象的相等性。 | |
boolean | exists | |
() | 测试此抽象路径名表示的文件或目录是否存在。 | |
File | getAbsoluteFile | |
() | 返回此抽象路径名的绝对形式。 | |
String | getAbsolutePath | |
() | 返回此抽象路径名的绝对路径名字符串。 | |
File | getCanonicalFile | |
() | 返回此抽象路径名的规范形式。 | |
String | getCanonicalPath | |
() | 返回此抽象路径名的规范路径名字符串。 | |
long | getFreeSpace | |
() | 通过此抽象路径名返回分区 named中未分配的字节数。 | |
String | getName | |
() | 返回此抽象路径名表示的文件或目录的名称。 | |
String | getParent | |
() | 返回此抽象路径名父项的路径名字符串,如果此路径名未指定父目录,则返回 null 。 | |
File | getParentFile | |
() | 返回此抽象路径名父项的抽象路径名,如果此路径名未指定父目录,则返回 null 。 | |
String | getPath | |
() | 将此抽象路径名转换为路径名字符串。 | |
long | getTotalSpace | |
() | 通过此抽象路径名返回分区 named的大小。 | |
long | getUsableSpace | |
() | 通过此抽象路径名返回分区 named上此虚拟机可用的字节数。 | |
int | hashCode | |
() | 计算此抽象路径名的哈希码。 | |
boolean | isAbsolute | |
() | 测试此抽象路径名是否为绝对路径。 | |
boolean | isDirectory | |
() | 测试此抽象路径名表示的文件是否为目录。 | |
boolean | isFile | |
() | 测试此抽象路径名表示的文件是否为普通文件。 | |
boolean | isHidden | |
() | 测试此抽象路径名指定的文件是否为隐藏文件。 | |
long | lastModified | |
() | 返回上次修改此抽象路径名表示的文件的时间。 | |
long | length | |
() | 返回此抽象路径名表示的文件的长度。 | |
String | ||
[] | list | |
() | 返回一个字符串数组,用于命名此抽象路径名表示的目录中的文件和目录。 | |
String | ||
[] | list | |
(FilenameFilter | ||
filter) | 返回一个字符串数组,用于命名由此抽象路径名表示的目录中的文件和目录,以满足指定的过滤器。 | |
File | ||
[] | listFiles | |
() | 返回一个抽象路径名数组,表示此抽象路径名表示的目录中的文件。 | |
File | ||
[] | listFiles | |
(FileFilter | ||
filter) | 返回一个抽象路径名数组,表示此抽象路径名表示的目录中满足指定过滤器的文件和目录。 | |
File | ||
[] | listFiles | |
(FilenameFilter | ||
filter) | 返回一个抽象路径名数组,表示此抽象路径名表示的目录中满足指定过滤器的文件和目录。 | |
static File | ||
[] | listRoots | |
() | 列出可用的文件系统根目录。 | |
boolean | mkdir | |
() | 创建此抽象路径名指定的目录。 | |
boolean | mkdirs | |
() | 创建此抽象路径名指定的目录,包括任何必需但不存在的父目录。 | |
boolean | renameTo | |
(File | ||
dest) | 重命名此抽象路径名表示的文件。 | |
boolean | setExecutable | |
(boolean executable) | 一种方便的方法,用于设置此抽象路径名的所有者执行权限。 | |
boolean | setExecutable | |
(boolean executable, boolean ownerOnly) | 设置此抽象路径名的所有者或每个人的执行权限。 | |
boolean | setLastModified | |
(long time) | 设置此抽象路径名指定的文件或目录的上次修改时间。 | |
boolean | setReadable | |
(boolean readable) | 一种方便的方法,用于设置此抽象路径名的所有者读取权限。 | |
boolean | setReadable | |
(boolean readable, boolean ownerOnly) | 设置此抽象路径名的所有者或每个人的读取权限。 | |
boolean | setReadOnly | |
() | 标记此抽象路径名指定的文件或目录,以便仅允许读取操作。 | |
boolean | setWritable | |
(boolean writable) | 一种方便的方法,用于设置此抽象路径名的所有者写入权限。 | |
boolean | setWritable | |
(boolean writable, boolean ownerOnly) | 设置此抽象路径名的所有者或每个人的写入权限。 | |
Path | toPath | |
() | 返回从此抽象路径构造的java.nio.file.Path对象。 | |
String | toString | |
() | 返回此抽象路径名的路径名字符串。 | |
URI | toURI | |
() | 构造一个表示此抽象路径名的 file: URI。 | |
URL | toURL | |
() | 已过时。 | |
此方法不会自动转义URL中非法的字符。 |
8.3 文件输入输出流 FileInputStream FileOutputStream
//创建文件字节输入流,用来从文件中读取字节数据
FileInputStream fis=new FileInputStream_(file);
用FileOutputStream类 向文件中写入数据
FileOutputStream fos = new FileOutputStream(file)_;
FileInputStream_方法摘要_
变量和类型 | 方法 | 描述 |
---|---|---|
int | available | |
() | 返回可以从此输入流中读取(或跳过)的剩余字节数的估计值,而不会被下一次调用此输入流的方法阻塞。 | |
void | close | |
() | 关闭此文件输入流并释放与该流关联的所有系统资源。 | |
protected void | finalize | |
() | 不推荐使用,要删除:此API元素将在以后的版本中删除。 | |
finalize方法已被弃用,将被删除。 | ||
FileChannel | getChannel | |
() | 返回与此文件输入流关联的唯一FileChannel对象。 | |
FileDescriptor | getFD | |
() | 返回 FileDescriptor对象,该对象表示与此 FileInputStream正在使用的文件系统中的实际文件的连接。 | |
int | read | |
() | 从此输入流中读取一个字节的数据。 | |
int | read | |
(byte[] b) | 从此输入流 b.length最多 b.length字节的数据读 b.length字节数组。 | |
int | read | |
(byte[] b, int off, int len) | 从此输入流 len最多 len字节的数据读入一个字节数组。 | |
long | skip | |
(long n) | 跳过并从输入流中丢弃 n字节的数据。 |
FileOutputStream 方法摘要
变量和类型 | 方法 | 描述 |
---|---|---|
void | close | |
() | 关闭此文件输出流并释放与此流关联的所有系统资源。 | |
protected void | finalize | |
() | 不推荐使用,要删除:此API元素将在以后的版本中删除。 | |
finalize方法已被弃用,将被删除。 | ||
FileChannel | getChannel | |
() | 返回与此文件输出流关联的唯一FileChannel对象。 | |
FileDescriptor | getFD | |
() | 返回与此流关联的文件描述符。 | |
void | write | |
(byte[] b) | 将指定字节数组中的 b.length字节写入此文件输出流。 | |
void | write | |
(byte[] b, int off, int len) | 将从偏移量 off开始的指定字节数组中的 len字节写入此文件输出流。 | |
void | write | |
(int b) | 将指定的字节写入此文件输出流。 |
/**
* 使用文件字节输入流,从文件中读取一个字节数据、多个字节数据到程序中。
*/
public class FileInputStreamOperate {
public static void main(String[] args) {
//创建File文件对象
File file=new File("F:\\intellij2020-1\\idea\\JavaBook\\src\\chap8\\task8_1\\Example8_2\\demo2.txt");
try {
//如果文件不存在,则创建文件
if(!file.exists())
{
file.createNewFile();
}
//创建文件字节输入流,用来从文件中读取字节数据
FileInputStream fis=new FileInputStream(file);
//一次读一个字节
System.out.println("以字节为单位读取文件内容,一次读一个字节:");
int tempbyte;
//文件没有结束 如果等于-1表示当前位置没有数据 读到末尾
while((tempbyte=fis.read()) !=-1 ){
//输入控制台 一个字节
System.out.write(tempbyte);
输出控制台 一个字节
//System.out.print(tempbyte);
}
//关闭输入流
fis.close();
FileOutputStream fos=new FileOutputStream(file,true);
//一次读取多个字节
System.out.println("\n以字节为单位读取文件内容,一次读多个字节:");
//创建文件字节输入流,用来从文件中读取字节数据
fis=new FileInputStream(file);
//定义 一个字节数组,一次读取64个字节
byte[] tempbytes = new byte[64];
//读入多个字节到字节数组中,byteread为一次读入的字节数
fis.read(tempbytes);
//输入控制台 多个字节 从0到30位置
System.out.write(tempbytes,0,30);
//文件没有结束 如果等于-1表示当前位置没有数据 读到末尾
while ((tempbyte = fis.read(tempbytes))!=-1){
//输入控制台 多个字节 从0到30位置
System.out.write(tempbytes,0,30);
输出控制台 多个字节
//System.out.print(tempbytes);
}
fis.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* 例8_3 用FileOutputStream类读出 写入文件的数据
*/
public class FileInputOutputOperate {
public static void main(String[] args){
try{
//创建文件
File file=new File("demo.txt");
if(!file.exists()){
file.createNewFile();
}
//写入文件
FileOutputStream fos=new FileOutputStream(file,true);
byte[] b="Hello,world".getBytes();
fos.write(b);
//从文件中读取
FileInputStream fin=new FileInputStream(file);
byte[] b1=new byte[50];
int temp=0;
String str="";
while((temp=fin.read(b1))!=-1){
System.out.println(new String(b1));
}
//关闭字节流
fin.close();
fos.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
/**
* 例8_3 用FileOutputStream类 向文件中写入数据
* 文件字节输出流 操作 向目标文件写入数据
* 注意捕捉异常
*/
public class FileOutputStreamOperate {
public static void main(String[] args) {
try {
//实例化一个文件File,不存在自动创建一个空的
File file = new File("F:\\intellij2020-1\\idea\\JavaBook\\src\\chap8\\task8_1\\Example8_3\\demo3.txt");
if (!file.exists()) {
file.createNewFile();
}
FileOutputStream fos = new FileOutputStream(file);
// 写一个整数,该整数范围最好在-128~127字节,否则其高位数据被丢失
fos.write(97);
// 写一个字节数组,或者部分
byte b[] = { 'a', 'b', 'c', 'd', 'e' };
fos.write(b);
fos.write(b, 0, 2); //局部写入
// 写一个字符串
fos.write("hello world!".getBytes()); // 把字符串转化为字节数组并写入到流中
// 关闭文件字节输出流
fos.close();
//通过文件字节输入流读取
byte[] buf = new byte[1024];
//通过文件字节输入流 构造方法 创建输入流对象
FileInputStream fis = new FileInputStream(file);
int len = fis.read(buf); // 读取内容到字节数组中
// String构造函数 把字节数组转化为字符串
System.out.println(new String(buf, 0, len));
System.out.println(buf); //输出字节
// 关闭文件字节输入流
fis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
任务实施
任务8.2 使用字符流设计记事本
8.4 字符流 FileReader FileWriter
以字符长度为处理单位。字符流操作效率比字节流高,字符流操作使用了缓冲区,通过缓冲区操作文件。
//创建文件字符输入流 从指定文件中读取字符数据
FileReader fr = new FileReader_(file1); // 从源文件读数据
//创建文件字符输出流 将字符数据写入指定文件中 继承了文件字节输出流OutputStreamWriter
FileWriter fw = new FileWriter(file2)_; // 将修改好的写入新文件
FileReader 方法摘要
变量和类型 | 方法 | 描述 |
---|---|---|
abstract void | close | |
() | 关闭流并释放与其关联的所有系统资源。 | |
void | mark | |
(int readAheadLimit) | 标记流中的当前位置。 | |
boolean | markSupported | |
() | 判断此流是否支持mark()操作。 | |
static Reader | nullReader | |
() | 返回不读取任何字符的新 Reader 。 | |
int | read | |
() | 读一个字符。 | |
int | read | |
(char[] cbuf) | 将字符读入数组。 | |
abstract int | read | |
(char[] cbuf, int off, int len) | 将字符读入数组的一部分。 | |
int | read | |
(CharBuffer | ||
target) | 尝试将字符读入指定的字符缓冲区。 | |
boolean | ready | |
() | 判断此流是否可以读取。 | |
void | reset | |
() | 重置流。 | |
long | skip | |
(long n) | 跳过字符。 | |
long | transferTo | |
(Writer | ||
out) | 读取此阅读器中的所有字符,并按照读取的顺序将字符写入给定的编写器。 |
FileWriter 方法摘要
变量和类型 | 方法 | 描述 |
---|---|---|
Writer | append | |
(char c) | 将指定的字符追加到此writer。 | |
Writer | append | |
(CharSequence | ||
csq) | 将指定的字符序列追加到此writer。 | |
Writer | append | |
(CharSequence | ||
csq, int start, int end) | 将指定字符序列的子序列追加到此writer。 | |
abstract void | close | |
() | 关闭流,先冲洗它。 | |
abstract void | flush | |
() | 刷新流。 | |
static Writer | nullWriter | |
() | 返回一个新的 Writer ,它丢弃所有字符。 | |
void | write | |
(char[] cbuf) | 写一个字符数组。 | |
abstract void | write | |
(char[] cbuf, int off, int len) | 写一个字符数组的一部分。 | |
void | write | |
(int c) | 写一个字符。 | |
void | write | |
(String | ||
str) | 写一个字符串。 | |
void | write | |
(String | ||
str, int off, int len) | 写一个字符串的一部分。 |
/**
* 例8-4 将一个文件中的小写字母改为大写字母后 复制到另一个文件中
*/
public class FileReaderAndWriterOperate {
public static void main(String[] args) {
try {
File file1 = new File("F:\\intellij2020-1\\idea\\JavaBook\\src\\chap8\\task8_2\\Example8_4\\demo4.txt"); // 源文件
File file2 = new File("F:\\intellij2020-1\\idea\\JavaBook\\src\\chap8\\task8_2\\Example8_4\\democopy.txt"); // 修改后的文件
if (!file1.exists()) {
file1.createNewFile();
}
if (!file2.exists()) {
file2.createNewFile();
}
//创建文件字符输入流 从指定文件中读取字符数据
FileReader fr = new FileReader(file1); // 从源文件读数据
//创建文件字符输出流 将字符数据写入指定文件中 继承了文件字节输出流OutputStreamWriter
FileWriter fw = new FileWriter(file2); // 将修改好的写入新文件
//创建字符数组
char charTemp[] = new char[128];
int size = fr.read(charTemp); //fr读入字符数组中,并返回读取数组的个数
for (int k = 0; k < size; k++) {
char ch = charTemp[k];
if (ch >= 'a' && ch <= 'z') { //将小写转换为大写
charTemp[k] = (char) (ch - 32);
}
}
fw.write(charTemp, 0, size); //写入到新文件中
fw.close(); //文件字符输出流必须要关闭,否则不能写
fr.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
8.5 缓冲输入输出流 BufferedInputStream BufferedOutputStream BufferedReader BufferedWriter
BufferedInputStream 缓冲字节输入_方法摘要_
变量和类型 | 方法 | 描述 |
---|---|---|
int | available | |
() | 返回可以从此输入流中读取(或跳过)的字节数的估计值,而不会被下一次调用此输入流的方法阻塞。 | |
void | close | |
() | 关闭此输入流并释放与该流关联的所有系统资源。 | |
void | mark | |
(int readlimit) | 参见 mark方法 InputStream的总合同。 | |
boolean | markSupported | |
() | 测试此输入流是否支持 mark和 reset方法。 | |
int | read | |
() | 参见 read方法 InputStream的总合同。 | |
int | read | |
(byte[] b, int off, int len) | 从给定的偏移量开始,将此字节输入流中的字节读入指定的字节数组。 | |
void | reset | |
() | 参见 reset方法 InputStream的总合同。 | |
long | skip | |
(long n) | 见的总承包 skip的方法 InputStream 。 |
BufferedOutputStream 缓冲字节输出_方法摘要_
变量和类型 | 方法 | 描述 |
---|---|---|
void | flush | |
() | 刷新此缓冲的输出流。 | |
void | write | |
(byte[] b, int off, int len) | 将从偏移量 off开始的指定字节数组中的 len字节写入此缓冲输出流。 | |
void | write | |
(int b) | 将指定的字节写入此缓冲的输出流。 |
BufferedReader 缓冲字符输入_方法摘要_
变量和类型 | 方法 | 描述 |
---|---|---|
Stream | ||
<String |
| lines
() | 返回 Stream ,其元素是从此 BufferedReader读取的行。 |
| void | mark
(int readAheadLimit) | 标记流中的当前位置。 |
| boolean | markSupported
() | 判断此流是否支持mark()操作。 |
| int | read
() | 读一个字符。 |
| int | read
(char[] cbuf, int off, int len) | 将字符读入数组的一部分。 |
| String | readLine
() | 读一行文字。 |
| boolean | ready
() | 判断此流是否可以读取。 |
| void | reset
() | 将流重置为最新标记。 |
| long | skip
(long n) | 跳过字符。 |
BufferedWriter 缓冲字符输出_方法摘要_
变量和类型 | 方法 | 描述 |
---|---|---|
void | flush | |
() | 刷新流。 | |
void | newLine | |
() | 写一个行分隔符。 | |
void | write | |
(char[] cbuf, int off, int len) | 写一个字符数组的一部分。 | |
void | write | |
(int c) | 写一个字符。 | |
void | write | |
(String | ||
s, int off, int len) | 写一个字符串的一部分。 |
_/**
- 使用缓冲字节输入输出流 完成文件的复制
- BufferedInputStream 从文件字节输入流 读取文本
- BufferedOutputStream 将文本写入 文件字节输出流
- 构造方法 套接在文件字节输入输出流上_
FileInputStream fis = new FileInputStream_(srcFile);
BufferedInputStream bis = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream(desFile);
BufferedOutputStream bos = new BufferedOutputStream(fos);__ */
/**
* 使用缓冲字节输入输出流 完成文件的复制
* BufferedInputStream 从文件字节输入流 读取文本
* BufferedOutputStream 将文本写入 文件字节输出流
* 构造方法 套接在文件字节输入输出流上
*/
public class BufferedStreamOperate {
public static void main(String[] args) {
try {
File srcFile = new File("F:\\intellij2020-1\\idea\\JavaBook\\src\\chap8\\task8_2\\Example8_5\\demo5.txt");
File desFile = new File("F:\\intellij2020-1\\idea\\JavaBook\\src\\chap8\\task8_2\\Example8_5\\demo51.txt");
if (!srcFile.exists()) {
srcFile.createNewFile();
}
if (!desFile.exists()) {
desFile.createNewFile();
}
FileInputStream fis = new FileInputStream(srcFile);
BufferedInputStream bis = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream(desFile);
BufferedOutputStream bos = new BufferedOutputStream(fos);
System.out.println("复制文件:" + srcFile.length() + "字节");
byte data[] = new byte[(int) srcFile.length()];
while (bis.read(data) != -1) {
bos.write(data);
}
// 将缓冲区中的数据全部写出
bos.flush();
// 关闭流
bis.close();
bos.close();
System.out.println("复制完成");
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("using: java UseFileStream src des");
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
_/**
- 使用缓冲字符输入输出流 完成文件的复制
- _BufferedReader_从文件字符输入流 读取文本
- _BufferedWriter_将文本写入 文件字符输出流
- 构造方法 套接在文件字符输入输出流上
* - 输入输出 都新增了一个操作行的功能readline()、newline()
- readline() 读到一行的终止符
- newline()写入一个分行符,但不同操作系统,换行符不同 window-“/r/n” linux-“\n” macos-“\r”
*/_
/**
* 使用缓冲字符输入输出流 完成文件的复制
* BufferedReader 从文件字符输入流 读取文本
* BufferedWriter 将文本写入 文件字符输出流
* 构造方法 套接在文件字符输入输出流上
*
* 输入输出 都新增了一个操作行的功能readline()、newline()
* readline() 读到一行的终止符
* newline()写入一个分行符,但不同操作系统,换行符不同 window-"/r/n" linux-"\n" macos-"\r"
*/
public class BufferReaderAndWriter {
public static void main(String[] args) {
try {
File srcFile = new File("F:\\intellij2020-1\\idea\\JavaBook\\src\\chap8\\task8_2\\Example8_6\\demo6.txt");
File desFile = new File("F:\\intellij2020-1\\idea\\JavaBook\\src\\chap8\\task8_2\\Example8_6\\demo61.txt");
if (!srcFile.exists()) {
srcFile.createNewFile();
}
if (!desFile.exists()) {
desFile.createNewFile();
}
FileReader fr = new FileReader(srcFile);
BufferedReader br = new BufferedReader(fr);
FileWriter fw = new FileWriter(desFile);
BufferedWriter bw = new BufferedWriter(fw);
System.out.println("复制文件:" + srcFile.length() + "字节");
String str="";
while((str=br.readLine())!=null)
{
bw.write(str);
bw.newLine();
}
bw.flush();
// 关闭流
br.close();
bw.close();
System.out.println("复制完成");
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("using: java UseFileStream src des");
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
任务实施
任务8.3 使用数据流设计记事本
8.6 数据输入输出流 Data_Input_Stream DataOutputStream
Data_Input_Stream 数据输入_方法摘要_
变量和类型 | 方法 | 描述 |
---|---|---|
int | read | |
(byte[] b) | 从包含的输入流中读取一些字节数,并将它们存储到缓冲区数组 b 。 | |
int | read | |
(byte[] b, int off, int len) | 从包含的输入流 len最多 len个字节的数据读入一个字节数组。 | |
boolean | readBoolean | |
() | 参见 readBoolean方法 DataInput的总合同。 | |
byte | readByte | |
() | 见的总承包 readByte的方法 DataInput 。 | |
char | readChar | |
() | 见的总承包 readChar的方法 DataInput 。 | |
double | readDouble | |
() | 见的总承包 readDouble的方法 DataInput 。 | |
float | readFloat | |
() | 见的总承包 readFloat的方法 DataInput 。 | |
void | readFully | |
(byte[] b) | 参见 readFully方法 DataInput的总合同。 | |
void | readFully | |
(byte[] b, int off, int len) | 见的总承包 readFully的方法 DataInput 。 | |
int | readInt | |
() | 见的总承包 readInt的方法 DataInput 。 | |
String | readLine | |
() | 已过时。 | |
此方法无法将字节正确转换为字符。 | ||
long | readLong | |
() | 参见 readLong方法 DataInput的总合同。 | |
short | readShort | |
() | 见的总承包 readShort的方法 DataInput 。 | |
int | readUnsignedByte | |
() | 参见 readUnsignedByte方法 DataInput的总合同。 | |
int | readUnsignedShort | |
() | 见的总承包 readUnsignedShort的方法 DataInput 。 | |
String | readUTF | |
() | 参见 readUTF方法 DataInput的总合同。 | |
static String | readUTF | |
(DataInput | ||
in) | 从流in读取以modified UTF-8格式编码的Unicode字符串的表示; 然后将此字符串作为String返回。 | |
int | skipBytes | |
(int n) | 参见 skipBytes方法 DataInput的总合同。 |
DataOutputStream 数据输出_方法摘要_
变量和类型 | 方法 | 描述 |
---|---|---|
void | flush | |
() | 刷新此数据输出流。 | |
int | size | |
() | 返回计数器 written的当前值,即 written写入此数据输出流的字节数。 | |
void | write | |
(byte[] b, int off, int len) | 将从偏移量 off开始的指定字节数组中的 len字节写入基础输出流。 | |
void | write | |
(int b) | 将指定的字节(参数 b的低8位)写入基础输出流。 | |
void | writeBoolean | |
(boolean v) | 将 boolean写入基础输出流作为1字节值。 | |
void | writeByte | |
(int v) | 将 byte写入基础输出流作为1字节值。 | |
void | writeBytes | |
(String | ||
s) | 将字符串作为字节序列写入基础输出流。 | |
void | writeChar | |
(int v) | 将 char写入基础输出流,作为2字节值,高字节优先。 | |
void | writeChars | |
(String | ||
s) | 将字符串作为字符序列写入基础输出流。 | |
void | writeDouble | |
(double v) | 双参数传递给转换 long使用 doubleToLongBits方法在类 Double ,然后写入该 long值基础输出流作为8字节的数量,高字节。 | |
void | writeFloat | |
(float v) | 浮子参数的转换 int使用 floatToIntBits方法在类 Float ,然后写入该 int值基础输出流作为一个4字节的数量,高字节。 | |
void | writeInt | |
(int v) | 将 int写入基础输出流,为四个字节,高字节优先。 | |
void | writeLong | |
(long v) | 将 long写入基础输出流,为8字节,高字节优先。 | |
void | writeShort | |
(int v) | 将 short写入基础输出流作为两个字节,高字节优先。 | |
void | writeUTF | |
(String | ||
str) | 使用 modified UTF-8编码以与机器无关的方式将字符串写入基础输出流。 |
_/**
- 例8-7 定义学生信息,将这些信息变量保存到student.dat中,
- 再将这些信息从文件中读取出来显示在控制台上
- 基本输入输出直流 只能读取写入 字节字符,但不能读写JAVA基本类型数据
- 过滤器流就是有目标过滤字节或字符的数据流
- 数据流属于过滤器流的一种 构造方法 套接在文件输入输出流上
- 常用于网络传输
*/_
FileOutputStream fos=new FileOutputStream_(file);
//创建数据输出流对象-向字节输出流写入基本类型数据
DataOutputStream dos=new DataOutputStream(fos);
System.out.println(“开始写文件:”);
dos.writeInt(outSno);
dos.writeUTF(outName);
dos.writeChar(outSex);
dos.writeInt(outAge);
dos.writeDouble(outScore);
dos.close(); //关闭数据输出流 最晚打开最早关闭
fos.close()_; //关闭文件字节输出流
/**
* 例8-7 定义学生信息,将这些信息变量保存到student.dat中,
* 再将这些信息从文件中读取出来显示在控制台上
* 基本输入输出直流 只能读取写入 字节字符,但不能读写JAVA基本类型数据
* 过滤器流就是有目标过滤字节或字符的数据流
* 数据流属于过滤器流的一种 构造方法 套接在文件输入输出流上
* 常用于网络传输
*/
public class DataStreamOperate {
public static void main(String[] args) {
int outSno=10,inSno;
//保存学号、姓名、性别、年龄、成绩 定义输入 输出变量
String outName="zlh",inName;
char outSex='f',inSex;
int outAge=20,inAge;
double outScore=90.0,inScore;
try {
File file=new File("F:\\intellij2020-1\\idea\\JavaBook\\src\\chap8\\task8_3\\Example8_7\\student.dat");
if(!file.exists()){
file.createNewFile();
}
FileOutputStream fos=new FileOutputStream(file);
//创建数据输出流对象-向字节输出流写入基本类型数据
DataOutputStream dos=new DataOutputStream(fos);
System.out.println("开始写文件:");
dos.writeInt(outSno);
dos.writeUTF(outName);
dos.writeChar(outSex);
dos.writeInt(outAge);
dos.writeDouble(outScore);
dos.close(); //关闭数据输出流 最晚打开最早关闭
fos.close(); //关闭文件字节输出流
System.out.println("写文件结束");
/**
* 注意读取写入 数据顺序要一致
*/
FileInputStream fis=new FileInputStream(file);
//创建数据输入流对象 从字节输入流中读取基本类型数据
DataInputStream dis=new DataInputStream(fis);
System.out.println("开始读文件:");
inSno=dis.readInt();
inName=dis.readUTF();
inSex=dis.readChar();
inAge=dis.readInt();
inScore=dis.readDouble();
dis.close();
fis.close();
System.out.println("读文件结束");
System.out.println("从文件中读出的内容是:");
//字符串拼接
System.out.println("学号是"+inSno+"姓名是"+inName+"性别是"+inScore+"年龄是"+inAge+"成绩是"+inScore);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
8.7 对象输入输出流 ObjectInputStream ObjectOutputStream 实现Serializable接口
_ObjectInputStream 数据输入_方法摘要
变量和类型 | 方法 | 描述 |
---|---|---|
int | available | |
() | 返回可以不阻塞地读取的字节数。 | |
void | close | |
() | 关闭输入流。 | |
void | defaultReadObject | |
() | 从此流中读取当前类的非静态和非瞬态字段。 | |
protected boolean | enableResolveObject | |
(boolean enable) | 使流能够替换从流中读取的对象。 | |
ObjectInputFilter | getObjectInputFilter | |
() | 返回此流的序列化过滤器。 | |
int | read | |
() | 读取一个字节的数据。 | |
int | read | |
(byte[] buf, int off, int len) | 读入一个字节数组。 | |
boolean | readBoolean | |
() | 读入布尔值。 | |
byte | readByte | |
() | 读取一个8位字节。 | |
char | readChar | |
() | 读取16位字符。 | |
protected ObjectStreamClass | readClassDescriptor | |
() | 从序列化流中读取类描述符。 | |
double | readDouble | |
() | 读取64位双精度数。 | |
ObjectInputStream.GetField | readFields | |
() | 从流中读取持久字段并使其按名称可用。 | |
float | readFloat | |
() | 读取32位浮点数。 | |
void | readFully | |
(byte[] buf) | 读取字节,阻塞直到读取所有字节。 | |
void | readFully | |
(byte[] buf, int off, int len) | 读取字节,阻塞直到读取所有字节。 | |
int | readInt | |
() | 读取32位int。 | |
String | readLine | |
() | 已过时。 | |
此方法无法将字节正确转换为字符。 | ||
long | readLong | |
() | 读长64位。 | |
Object | readObject | |
() | 从ObjectInputStream中读取一个对象。 | |
protected Object | readObjectOverride | |
() | ObjectOutputStream的可信子类调用此方法,该子类使用受保护的无参数构造函数构造ObjectOutputStream。 | |
short | readShort | |
() | 读取16位短路。 | |
protected void | readStreamHeader | |
() | 提供readStreamHeader方法以允许子类读取和验证自己的流标头。 | |
Object | readUnshared | |
() | 从ObjectInputStream中读取“非共享”对象。 | |
int | readUnsignedByte | |
() | 读取无符号的8位字节。 | |
int | readUnsignedShort | |
() | 读取无符号16位短路。 | |
String | readUTF | |
() | 以 modified UTF-8格式读取字符串。 | |
void | registerValidation | |
(ObjectInputValidation | ||
obj, int prio) | 在返回图形之前注册要验证的对象。 | |
protected 类 |
(ObjectStreamClass
desc) | 加载等效于指定流类描述的本地类。 |
| protected Object | resolveObject
(Object
obj) | 此方法将允许ObjectInputStream的受信任子类在反序列化期间将一个对象替换为另一个对象。 |
| protected 类
(String
[] interfaces) | 返回实现代理类描述符中指定的接口的代理类; 子类可以实现此方法以从流中读取自定义数据以及动态代理类的描述符,从而允许它们为接口和代理类使用备用加载机制。 |
| void | setObjectInputFilter
(ObjectInputFilter
filter) | 设置流的序列化过滤器。 |
| int | skipBytes
(int len) | 跳过字节。 |
_ObjectOutputStream 数据输入_方法摘要
变量和类型 | 方法 | 描述 |
---|---|---|
protected void | annotateClass | |
(类 |
| protected void | annotateProxyClass
(类
| void | close
() | 关闭流。 |
| void | defaultWriteObject
() | 将当前类的非静态和非瞬态字段写入此流。 |
| protected void | drain
() | 排除ObjectOutputStream中的所有缓冲数据。 |
| protected boolean | enableReplaceObject
(boolean enable) | 使流能够替换写入流的对象。 |
| void | flush
() | 刷新流。 |
| ObjectOutputStream.PutField | putFields
() | 检索用于缓冲要写入流的持久字段的对象。 |
| protected Object | replaceObject
(Object
obj) | 此方法将允许ObjectOutputStream的受信任子类在序列化期间将一个对象替换为另一个对象。 |
| void | reset
() | 重置将忽略已写入流的任何对象的状态。 |
| void | useProtocolVersion
(int version) | 指定写入流时要使用的流协议版本。 |
| void | write
(byte[] buf) | 写一个字节数组。 |
| void | write
(byte[] buf, int off, int len) | 写一个子字节数组。 |
| void | write
(int val) | 写一个字节。 |
| void | writeBoolean
(boolean val) | 写一个布尔值。 |
| void | writeByte
(int val) | 写一个8位字节。 |
| void | writeBytes
(String
str) | 将String写为字节序列。 |
| void | writeChar
(int val) | 写一个16位字符。 |
| void | writeChars
(String
str) | 将String写为一系列字符。 |
| protected void | writeClassDescriptor
(ObjectStreamClass
desc) | 将指定的类描述符写入ObjectOutputStream。 |
| void | writeDouble
(double val) | 写一个64位双。 |
| void | writeFields
() | 将缓冲的字段写入流。 |
| void | writeFloat
(float val) | 写一个32位浮点数。 |
| void | writeInt
(int val) | 写一个32位的int。 |
| void | writeLong
(long val) | 写入64位长。 |
| void | writeObject
(Object
obj) | 将指定的对象写入ObjectOutputStream。 |
| protected void | writeObjectOverride
(Object
obj) | 子类用于覆盖默认writeObject方法的方法。 |
| void | writeShort
(int val) | 写一个16位的短。 |
| protected void | writeStreamHeader
() | 提供了writeStreamHeader方法,因此子类可以将自己的标头附加或预先添加到流中。 |
| void | writeUnshared
(Object
obj) | 将“非共享”对象写入ObjectOutputStream。 |
| void | writeUTF
(String
str) | 原始数据以 modified UTF-8格式写入此字符串。 |
_/**
- 例8-8 定义序列化的学生类
- 对象序列化Serializable 就是 把一个对象变为二进制的数据流的一种方法,实现对象的传输存储
- 对象实现Serializable接口 就完成对象序列化-》序列化对象
*/_
/**
* 例8-8 定义序列化的学生类
* 对象序列化 就是 把一个对象变为二进制的数据流的一种方法,实现对象的传输存储
* 对象实现Serializable接口 就完成对象序列化-》序列化对象
*/
public class Student implements Serializable{//实现了序列化接口
private int stuNO;
private String stuName;
private String sex;
private int age;
private double score;
public Student() {
super();
}
public int getStuNO() {
return stuNO;
}
public void setStuNO(int stuNO) {
this.stuNO = stuNO;
}
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
// toString在Object对象中 当我们打印一个对象的引用时,实际是默认调用这个对象的toString()方法
@Override
public String toString() {
// TODO Auto-generated method stub
return "学号是"+this.getStuNO()+"\t姓名是"+this.getStuName()+"\t性别是"+this.getSex()+"\t年龄是"+this.getAge()+"\t成绩是"+this.getScore();
}
}
_/**
- 例8-9 将若干个学生对象写入到文件中,再从该文件中读取出来下显示在控制台
- 学生对象必须实现序列化
- ObjectInputStream 对象输入流 从数据输入流中读取序列化对象
- ObjectOutputStream 对象输出流 将一个对象写入到目标设备上
- 对象输入输出流 构造方法套接在文件字节输入输出流上
- 可以用于网络传输
- 如果希望将对象保存在硬盘上,或者在网络间传输,这是需要将一个对象序列化为字节序列,这个过程就叫做对象的序列化操作。
- 相应的,如果需要将该字节序列再转换为对应的对象,这个过程就是反序列化。
* - 注意 在反序列化时,出现编码解析内容异常 出现乱码 解决:将txt的格式改为utf-8
*/_
//定义文件字节输出流、对象输出流
FileOutputStream fos=new FileOutputStream_(file);
ObjectOutputStream oos=new ObjectOutputStream(fos)_;//创建对象输出流
/**
* 例8-9 将若干个学生对象写入到文件中,再从该文件中读取出来下显示在控制台
* 学生对象必须实现序列化
* ObjectInputStream 对象输入流 从数据输入流中读取序列化对象
* ObjectOutputStream 对象输出流 将一个对象写入到目标设备上
* 对象输入输出流 构造方法套接在文件字节输入输出流上
* 可以用于网络传输
* 如果希望将对象保存在硬盘上,或者在网络间传输,这是需要将一个对象序列化为字节序列,这个过程就叫做对象的序列化操作。
* 相应的,如果需要将该字节序列再转换为对应的对象,这个过程就是反序列化。
*
* 注意 在反序列化时,出现编码解析内容异常 出现乱码 解决:将txt的格式改为utf-8
*/
public class ObjectStreamOperate {
public static void main(String[] args) {
File file=new File("F:\\intellij2020-1\\idea\\JavaBook\\src\\chap8\\task8_3\\Example8_9\\student1.dat");
try {
if(!file.exists())
{
file.createNewFile();
}
//定义文件字节输出流、对象输出流
FileOutputStream fos=new FileOutputStream(file);
ObjectOutputStream oos=new ObjectOutputStream(fos);//创建对象输出流
//创建序列化的对象
Student s1=new Student();
s1.setStuNO(1);
s1.setStuName("lili");
s1.setSex("f");
s1.setAge(20);
s1.setScore(85.0);
Student s2=new Student();
s2.setStuNO(2);
s2.setStuName("tom\t");
s2.setSex("m");
s2.setAge(19);
s2.setScore(95.0);
Student s3=new Student();
s3.setStuNO(3);
s3.setStuName("peter");
s3.setSex("m");
s3.setAge(21);
s3.setScore(75.0);
System.out.println("开始向文件写对象");
oos.writeObject(s1);
oos.writeObject(s2);
oos.writeObject(s3);
oos.close();
System.out.println("写文件写结束");
//定义文件字节输入流、对象输入流
FileInputStream fis=new FileInputStream(file);
ObjectInputStream ois=new ObjectInputStream(fis);
//toString在Object对象中 当我们打印一个对象的引用时,实际是默认调用这个对象的toString()方法
System.out.println("开始从文件读对象");
//对象转换
Student stu1=(Student) ois.readObject();
System.out.println(stu1);
Student stu2=(Student) ois.readObject();
System.out.println(stu2);
Student stu3=(Student) ois.readObject();
System.out.println(stu3);
ois.close();
System.out.println("读文件写结束");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
任务实施
任务8.4 时钟显示器设计
![I}B@OH{6%9V4{V(FLME4SD.png
8.8 多线程概述
线程是程序中执行的线程。 Java虚拟机允许应用程序同时运行多个执行线程。
每个线程都有优先权。 具有较高优先级的线程优先于具有较低优先级的线程执行。 每个线程可能也可能不会被标记为守护进程。 当在某个线程中运行的代码创建一个新的Thread对象时,新线程的优先级最初设置为等于创建线程的优先级,并且当且仅当创建线程是守护进程时才是守护进程线程。
当Java虚拟机启动时,通常会有一个非守护进程线程(通常调用某个指定类的名为main的方法)。 Java虚拟机继续执行线程,直到发生以下任一情况:
- 已调用类Runtime的exit方法,并且安全管理器已允许执行退出操作。
- 通过调用run方法返回或抛出超出run方法传播的异常,所有非守护程序线程的线程都已死亡。
有两种方法可以创建新的执行线程。 一种是将类声明为Thread的子类。 此子类应覆盖类Thread的run方法。 然后可以分配和启动子类的实例。
Thread类方法摘要(直接new实现)
变量和类型 | 方法 | 描述 |
---|---|---|
static int | activeCount | |
() | 返回当前线程thread group及其子组中活动线程数的估计值。 | |
void | checkAccess | |
() | 确定当前运行的线程是否具有修改此线程的权限。 | |
protected Object | clone | |
() | 抛出CloneNotSupportedException,因为无法有意义地克隆线程。 | |
int | countStackFrames | |
() | 不推荐使用,要删除:此API元素将在以后的版本中删除。 | |
此调用的定义取决于suspend() ,已弃用。 | ||
static Thread | currentThread | |
() | 返回对当前正在执行的线程对象的引用。 | |
static void | dumpStack | |
() | 将当前线程的堆栈跟踪打印到标准错误流。 | |
static int | enumerate | |
(Thread | ||
[] tarray) | 将当前线程的线程组及其子组中的每个活动线程复制到指定的数组中。 | |
static Map | ||
<Thread | ||
,StackTraceElement | ||
[]> | getAllStackTraces | |
() | 返回所有活动线程的堆栈跟踪映射。 | |
ClassLoader | getContextClassLoader | |
() | 返回此线程的上下文 ClassLoader 。 | |
static Thread.UncaughtExceptionHandler | getDefaultUncaughtExceptionHandler | |
() | 返回由于未捕获的异常而导致线程突然终止时调用的默认处理程序。 | |
long | getId | |
() | 返回此Thread的标识符。 | |
String | getName | |
() | 返回此线程的名称。 | |
int | getPriority | |
() | 返回此线程的优先级。 | |
StackTraceElement | ||
[] | getStackTrace | |
() | 返回表示此线程的堆栈转储的堆栈跟踪元素数组。 | |
Thread.State | getState | |
() | 返回此线程的状态。 | |
ThreadGroup | getThreadGroup | |
() | 返回此线程所属的线程组。 | |
Thread.UncaughtExceptionHandler | getUncaughtExceptionHandler | |
() | 返回此线程由于未捕获的异常而突然终止时调用的处理程序。 | |
static boolean | holdsLock | |
(Object | ||
obj) | 当且仅当当前线程在指定对象上保存监视器锁时,返回 true 。 | |
void | interrupt | |
() | 中断此线程。 | |
static boolean | interrupted | |
() | 测试当前线程是否已被中断。 | |
boolean | isAlive | |
() | 测试此线程是否存活。 | |
boolean | isDaemon | |
() | 测试此线程是否为守护程序线程。 | |
boolean | isInterrupted | |
() | 测试此线程是否已被中断。 | |
void | join | |
() | 等待这个线程死亡。 | |
void | join | |
(long millis) | 此线程最多等待 millis毫秒。 | |
void | join | |
(long millis, int nanos) | 此线程最多等待 millis毫秒加上 nanos纳秒。 | |
static void | onSpinWait | |
() | 表示调用者暂时无法进展,直到其他活动发生一个或多个操作为止。 | |
void | resume | |
() | 已过时。 | |
此方法仅适用于suspend() ,由于它易于死锁,因此已被弃用。 | ||
void | run | |
() | 如果此线程是使用单独的Runnable运行对象构造的,则调用该Runnable对象的run方法; 否则,此方法不执行任何操作并返回。 | |
void | setContextClassLoader | |
(ClassLoader | ||
cl) | 为此Thread设置上下文ClassLoader。 | |
void | setDaemon | |
(boolean on) | 将此线程标记为 daemon线程或用户线程。 | |
static void | setDefaultUncaughtExceptionHandler | |
(Thread.UncaughtExceptionHandler | ||
eh) | 设置当线程由于未捕获的异常而突然终止时调用的默认处理程序,并且没有为该线程定义其他处理程序。 | |
void | setName | |
(String | ||
name) | 将此线程的名称更改为等于参数 name 。 | |
void | setPriority | |
(int newPriority) | 更改此线程的优先级。 | |
void | setUncaughtExceptionHandler | |
(Thread.UncaughtExceptionHandler | ||
eh) | 设置当此线程由于未捕获的异常而突然终止时调用的处理程序。 | |
static void | sleep | |
(long millis) | 导致当前正在执行的线程休眠(暂时停止执行)指定的毫秒数,具体取决于系统计时器和调度程序的精度和准确性。 | |
static void | sleep | |
(long millis, int nanos) | 导致当前正在执行的线程休眠(暂时停止执行)指定的毫秒数加上指定的纳秒数,具体取决于系统定时器和调度程序的精度和准确性。 | |
void | start | |
() | 导致此线程开始执行; Java虚拟机调用此线程的run方法。 | |
void | stop | |
() | 已过时。 | |
这种方法本质上是不安全的。 | ||
void | suspend | |
() | 已过时。 | |
此方法已被弃用,因为它本身就容易出现死锁。 | ||
String | toString | |
() | 返回此线程的字符串表示形式,包括线程的名称,优先级和线程组。 | |
static void | yield | |
() | 向调度程序提示当前线程是否愿意产生其当前使用的处理器。 |
Runnable接口方法摘要(用Thread构造方法)
变量和类型 | 方法 | 描述 |
---|---|---|
void | run | |
() | 当使用实现接口 Runnable的对象来创建线程时,启动该线程会导致在该单独执行的线程中调用该对象的 run方法。 |
8.9 Java多线程实现
/**
* 例8-10 应用继承Thread类创建线程
*/
public class MyThread extends Thread {
//重写run()方法 定义创建
public void run() {
for(int i=0;i<5;i++) {
System.out.println("invoke MyThread "+i+ " run method");
try {
//线程休眠时间间隔
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) { // main方法测试线程的创建与启动
// 实例化MyThread的对象 继承了Thread 直接new对象MyThread
MyThread myThread = new MyThread();
myThread.start(); // 调用myThread对象的start方法启动一个线程
}
}
/**
* 例8-11 通过Runable接口实现多线程 定义MyRunable类实现Runnable接口,并实现接口中的run方法。
*/
public class MyRunable implements Runnable {
public void run() {
for(int i=0;i<5;i++) {
System.out.println("invoke MyThread "+i+ " run method");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) { // main方法测试线程的创建与启动
// 建立MyRunable类的对象,以此对象为参数建立Thread类的对象
// 采用接口更灵活, 实现多个接口
Thread thread = new Thread(new MyRunable());
thread.start(); // 调用thread对象的start方法启动一个线程
}
}
_
8.10 线程的状态控制
新建- new或者thread构造建立线程对象后,处于新建状态
就绪- 调用start方法后进入就绪状态
死亡- 线程完成全部任务后 或者 强制调用stop或destory方法终止(目前一般不用,用return或标志位)
阻塞 线程暂时停止就进入阻塞状态,如调用sleep睡眠、yield让出CPU、join等待另一个线程。
例8-12 线程状态转变示例
/**
* 例8-12 线程状态转变示例
* 新建-就绪-死亡-阻塞
*/
public class MyThreadState implements Runnable {
//1 在run()方法中定义线程
public void run() {
System.out.println("MyThread start!");
for(int i=0;i<5;i++){
System.out.println("invoke MyThread run method");
}
}
public static void main(String[] args) {
//2 实例化线程对象
Thread thread = new Thread(new MyThreadState()); // 新生状态
//3 新建
System.out.println("MyThread create!");
thread.start(); // 就绪状态,获得CPU后就能运行
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//4 死亡停止 方法已经过期
thread.stop(); // 死亡状态
System.out.println("MyThread stop!");
}
}
例8-13 线程强制销毁示例
/**
* 例8-13 线程强制销毁示例
* 因为Thread的stop、destory已经过时,可以用新的方法:
* 1 在run方法中执行return线程-结束
* 2 在while条件中设置一个标志位,等于false循环结束,线程也就结束
*/
public class MyRunable2 implements Runnable {
private boolean isStop; //线程是否停止的标志位
public void run() {
System.out.println("Thread run!");
//判断isStop是否为true
while (!isStop){
System.out.println("invoke MyRunable run method");
try {
//每次循环休眠 500毫秒
Thread.sleep(500);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void stop(){ //终止线程
isStop=true;
System.out.println("Thread stop!");
}
public static void main(String[] args) {
//实例化线程对象
MyRunable2 myRunable=new MyRunable2();
Thread thread = new Thread(myRunable);
//启动线程
System.out.println("Thread create!");
thread.start();
//线程 休眠5秒后 结束
try {
Thread.sleep(5000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
myRunable.stop(); //正确的停止线程的方法
}
}
例8-14 线程yield方法示例
让出CPU资源给其他线程或程序运行
//定义一个线程 run方法中为执行内容
public class MyThread2 implements Runnable {
private String name;
MyThread2(String s) {
this.name = s;
}
public void run() {
for (int i = 1; i <= 6; i++) {
System.out.println(name + ": " + i);
if (i % 2 == 0) {
//阻塞状态 让出CPU使用权、运行态变成就绪态,让给下个线程
Thread.yield();
}
}
}
}
package chap8.task8_4.Example8_14;
/**
* 例8-14 线程yield方法示例
* 让出CPU资源给其他线程或程序运行
*/
public class YieldTest {
public static void main(String[] args) {
//构造2个线程对象
Runnable r1 = new MyThread2("S1");
Runnable r2 = new MyThread2("S2");
//实例化线程对象 并启动
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
t2.start();
//休眠2毫秒时间 打印输出的内容
try {
Thread.sleep(2);
}catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("main method over!");
}
}
例题8-15 线程join方法示例
package chap8.task8_4.Example8_15;
//定义一个父亲线程FatherThread
public class FatherThread implements Runnable {
public void run() {
System.out.println("爸爸想抽烟,发现烟抽完了");
System.out.println("爸爸让儿子去买包红塔山");
//实例化线程对象 并启动son线程
Thread son = new Thread(new SonThread());
son.start();
System.out.println("爸爸等儿子买烟回来");
try {
//join含义:等待son线程执行完毕,father线程才继续执行
son.join();
}
catch (InterruptedException e) {
System.out.println("爸爸出门去找儿子跑哪去了");
System.exit(1);
}
System.out.println("爸爸高兴的接过烟开始抽,并把零钱给了儿子");
}
}
package chap8.task8_4.Example8_15;
//定义一个儿子线程SonThread
public class SonThread implements Runnable {
public void run() {
String tabs="\t\t\t";
System.out.println(tabs+"儿子出门去买烟");
System.out.println(tabs+"儿子买烟需要3分钟");
try {
for (int i = 0; i < 3;) {
Thread.sleep(500);
System.out.println(tabs+"儿子出去第" + ++i + "分钟");
}
}
catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(tabs+"儿子买烟回来了");
}
}
package chap8.task8_4.Example8_15;
/**
* 例题8-15 线程join方法示例
* 注意:多线程中run()方法中对文件读写 避免发生冲突互斥 采用互斥锁的机制
*/
public class JoinTest {
public static void main(String[] args) {
System.out.println("爸爸和儿子的故事");
//实例化线程对象 并启动父亲线程
//加入son.join(),子执行后 父才执行
Thread father = new Thread(new FatherThread());
father.start();
}
}
任务实施
/**
* This class is a simple JFrame implementation to explain how to display time
* dynamically on the JSwing-based interface.
* @author Edison
*/
/**
* 任务8_4时钟显示器设计
* 时钟显示器是在主界面状态栏上动态显示日历与时间
* 设计步骤:
* 1、设计时钟显示器界面
* 2、实现Runnable接口,在run()方法中增加获取当前时间
* 3、最后将获取到的时间设置到界面上
*/
public class DTimeFrame extends JFrame implements Runnable {
private JFrame frame;
private JPanel timePanel;
private JLabel timeLabel;
private JLabel displayArea;
private String DEFAULT_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
private int ONE_SECOND = 1000;
public DTimeFrame() {
timePanel = new JPanel();
timeLabel = new JLabel("当前时间是: ");
timeLabel.setForeground(Color.red);
displayArea = new JLabel();
timePanel.add(timeLabel);
timePanel.add(displayArea);
this.add(timePanel);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setSize(new Dimension(250, 80));
this.setLocationRelativeTo(null);
this.setTitle("时钟显示器");
}
public void run() {
while (true) {
SimpleDateFormat dateFormatter = new SimpleDateFormat(
DEFAULT_TIME_FORMAT);
displayArea.setText(dateFormatter.format(Calendar.getInstance()
.getTime()));
try {
Thread.sleep(ONE_SECOND);
} catch (Exception e) {
displayArea.setText("Error!!!");
}
}
}
public JPanel getTimePanel() {
return timePanel;
}
public void setTimePanel(JPanel timePanel) {
this.timePanel = timePanel;
}
public static void main(String arg[]) {
DTimeFrame df2 = new DTimeFrame();
df2.setVisible(true);
Thread thread1 = new Thread(df2);
thread1.start();
}
}
/**
* @author cmy
* @version 1.0
* @date 2022/3/31 17:31
* @description 多线程文件读写 避免发生冲突互斥 采用互斥锁的机制
*
*/
/**
* 没加锁前 两个线程同步实现count自增。正确count值为2000,但线程冲突,就会小于2000
*/
//public class fileThread {
// public static void main(String[] args) throws Exception {
// Thread aThread = new thread1();
// Thread bThread = new thread2();
// aThread.start();
// bThread.start();
// aThread.join();
// bThread.join();
// System.out.println(num.count);
// }
//}
//
//class num {
// public static int count = 0;
//}
//
//class thread1 extends Thread{
// @Override
// public void run() {
// for(int i = 0;i<1000;i++) {
// num.count ++;
// }
// System.out.println("thread1 over!");
// }
//}
//
//class thread2 extends Thread{
// @Override
// public void run() {
// for(int i = 0;i<1000;i++) {
// num.count ++;
// }
// System.out.println("thread2 over!");
// }
//}
/**
* 加锁后
* synchronized 控制多个并发线程的访问 多线程访问冲突的解决方式 实现同步
* 表示用Counter.lock实例作为锁,两个线程在执行各自的synchronized(lock)代码块时,
* 必须先获得锁,才能进入代码块进行。执行结束后,在synchronized语句块结束会自动释放锁。
* 这样一来,对count变量进行读写就不可能同时进行。
*/
public class fileThread {
public static void main(String[] args) throws Exception {
Thread aThread = new thread1();
Thread bThread = new thread2();
aThread.start();
bThread.start();
aThread.join();
bThread.join();
System.out.println(num.count);
}
}
class num {
public static final Object lock = new Object();
public static int count = 0;
}
class thread1 extends Thread{
@Override
public void run() {
for(int i = 0;i<1000;i++)
synchronized (num.lock) { //注意加锁对象必须是同一个实例
num.count ++;
}
System.out.println("thread1 over!");
}
}
class thread2 extends Thread{
@Override
public void run() {
for(int i = 0;i<1000;i++)
synchronized (num.lock) { //注意加锁对象必须是同一个实例
num.count ++;
}
System.out.println("thread2 over!");
}
}