本节主要掌握字节流和字符流的联系和区别、理解多线程的益处,了解 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