本节主要掌握字节流和字符流的联系和区别、理解多线程的益处,了解 Thread 与 Runable 的基本用法、熟悉start、run、sleep、wait等线程常见方法、优先级设置。并熟练写出同步代码块和同步函数的售票窗口代码。
Java 的 IO 操作
1.Java 根据数据的流向可以分为输入输出流,根据数据的类型可以分为字节与字符流。
2.字节流
可以处理所有类型数据(如,MP3、图片、文字和视频等),读取时读到一个字节就返回一个字节。
Java中对应的类以Stream结尾。
3.字符流
处理纯文本为主,读到一个或多个字节,先查找制定编码,然后返回查找的字符。
Java中对应的类以Reader、Writer结尾。
线程与进程
1.线程
程序中单独顺序的控制流。线程本身依靠程序运行,线程是程序中的顺序控制流,只能使用分配给程序的资源和环境。
2.进程
执行中的程序。一个进程可以包含一个或多个线程,但至少一个。
3.单线程
程序中只有一个线程。主方法就是一个主线程。
4.多线程
多线程是在一个程序中,运行的多个任务,多线程的目的在于更好地使用CPU资源。
线程的实现
Java中线程的实现分为两种:继承Thread类和实现Runable接口。
1.Thread类
它是Java.lang包中的类,继承Thread类,必须重写Run方法。
2.Runable接口
也必须重写Run方法。
注:
线程的启动是使用 start 方法的。
package Thread_Pack;
public class MyThread extends Thread{
private String name;
public MyThread(String name) {
// TODO Auto-generated constructor stub
this.name = name;
}
public void run() {
for(int i=0;i<10;i++){
System.out.println(name);
// super.run();
}
}
}
package Thread_Pack;
public class Thread_Class {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
MyThread t1 = new MyThread("A");
MyThread t2 = new MyThread("B");
// t1.run();
// t2.run();
t1.start();
t2.start();
// MyRun implements Runable 并复写run方法 也可实现线程调用
}
}
根据优先级,运行线程方法。
优先级关键字 | 优先级 |
MIN_PRIORITY | 1 |
NORM_PRIORITY | 5(默认) |
MAX_PRIORITY | 10 |
package Runable_Pack;
class ThRu implements Runnable{
public void run() {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" : "+i);
}
}
}
public class Runable_Class {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
ThRu tr1 = new ThRu();
ThRu tr2 = new ThRu();
ThRu tr3 = new ThRu();
Thread th1 = new Thread(tr1,"A");
Thread th2 = new Thread(tr2,"B");
Thread th3 = new Thread(tr3,"C");
th1.setPriority(Thread.MIN_PRIORITY);
th2.setPriority(Thread.NORM_PRIORITY);
th3.setPriority(Thread.MAX_PRIORITY);
th1.start();
th2.start();
th3.start();
}
}
注:
未明白为什么Sleep函数处,需要添加 Try/Catch Block。
线程的状态
创建状态:准备好一个多线程对象;
就绪状态:准备好了Start(),等待CPU调度
运行状态:执行Run方法
阻塞状态:暂时停止执行,可将资源交予其它线程。
终止状态:线程销毁,死亡状态。
线程常用的方法
方法名称 | 功能 |
getName | 获取线程名称 |
currentThread | 取得当前线程对象 |
isAlive | 判断线程是否启动 |
join | 线程的强行运行 |
sleep | 线程的休眠 |
yield | 线程的礼让 |
线程的同步与死锁
代码块与方法都可以通过 Synchronized 方法实现同步。
代码块同步的代码示例
package Synchronized_Pack;
// 多窗口售票
class MyDemo implements Runnable{
private int ticket = 5; // 剩余票数目
public void run(){
for (int i = 0; i < 100; i++) {
if (ticket>0) {
synchronized(this){
if (ticket>0) {
Thread.sleep(500);
System.out.println(ticket--);
}
}
}
}
}
public class Synchronized_Class {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
MyDemo myd = new MyDemo();
// 有 3 个售票窗口
Thread t1 = new Thread(myd);
Thread t2 = new Thread(myd);
Thread t3 = new Thread(myd);
t1.start();
t2.start();
t3.start();
}
}
代码输出:
C : 0
B : 0
A : 0
B : 1
A : 1
C : 1
A : 2
B : 2
C : 2
A : 3
C : 3
B : 3
A : 4
B : 4
C : 4
方法同步的代码块示例
package Synchronized_Pack;
// 多窗口售票
class MyDemo implements Runnable{
private int ticket = 5;
public void run(){
for(int i=0;i<10;i++){
if (ticket>0) {
tell();
}
}
}
public synchronized void tell() {
if (ticket>0) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(ticket--);
}
}
}
public class Synchronized_Class {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
MyDemo myd = new MyDemo();
// 有 3 个售票窗口
Thread t1 = new Thread(myd);
Thread t2 = new Thread(myd);
Thread t3 = new Thread(myd);
t1.start();
t2.start();
t3.start();
}
}
代码输出
5
4
3
2
1