线程回顾

1.程序、进程、线程

程序: Program,是一个指令的集合

进程: Process,(正在执行中的程序)是一个静态的概念,进程是程序的一次静态执行过程, 占用特定的地址空间.

每个进程都是独立的,由 3 部分组成 cpu,data,code

缺点:内存的浪费,cpu 的负担

线程: 是进程中一个“单一的连续控制流程”,线程又被称为轻量级进程,一个进程可拥有多个并行的(concurrent)线程  一个进程中的线程共享相同的内存单元/内存地址空间(指共享进程空间) 由于线程间的通信是在同一地址空间上进行的,所以不需要额外的通信机制,这就使得通信更简便而且信息传递的速度也更快。

2.在 Java 中创建线程的两种方式

1) 继承 Thread

2) 实现 Runnable 接口

3 线程的生命周期

4 同步与死锁

1) 同步方法  同步监视器为当前对象 this

2) 同步代码块(同步监视器/共享资源的对象){
}
过多的同步就会导致死锁

5.线程间的通信

1) wait()  等待

2) notify()  唤醒

3) notifyAll()

需要与同步一起使用

6.案例

编写两个线程,一个线程打印 1-52 的整数,另一个线程打印字母 A-Z。打印顺序为 12A34B56C….5152Z。即按照整数和

字母的顺序从小到大打印,并且每打印两个整数后,打印一个字母,交替循环打印,直到打印到整数 52 和字母 Z 结束。

步骤:

1) 编写打印类 Printer,声明私有属性 index,初始值为 1,用来表示是第几次打印。

2) 在打印类 Printer 中编写打印数字的方法 print(int i),3 的倍数就使用 wait()方法等待,否则就输出 i,使用 notifyAll()进行唤醒其它线程。

3) 在打印类 Printer 中编写打印字母的方法 print(char c),不是 3 的倍数就等待,否则就打印输出字母 c,使用 notifyAll()进行唤醒其它线程。

 1 public class Printer {
 2     
 3     private int index = 1;//用于统计第几次打印
 4     
 5     public synchronized void print(int number) {  //打印数字
 6         while(index%3 == 0) { //3的倍数则等待
 7             try {
 8                 super.wait();
 9             } catch (InterruptedException e) {
10                 // TODO 自动生成的 catch 块
11                 e.printStackTrace();
12             }
13         }
14         System.out.print(number);
15         index++;
16         super.notifyAll();//唤醒在Printer这个对象上的所有的等待的线程
17         
18     }
19     
20     public synchronized void print(char c) {
21         while(index%3 != 0) { //不是3的倍数则等待
22             try {
23                 super.wait();
24             } catch (InterruptedException e) {
25                 // TODO 自动生成的 catch 块
26                 e.printStackTrace();
27             }
28         }
29         System.out.print(c);
30         index++;
31         super.notifyAll();//唤醒在Printer这个对象上的所有的等待的线程
32 
33     }
34 }
View Code

 

4) 编写打印数字的线程 NumberPrinter 继承 Thread 类,声明私有属性 private Printer p;在构造方法中进行赋值,实现父类的 run 方法,调用 Printer 类中的输出数字的方法。

 1 public class NumberPrinter extends Thread{ //打印数字的线程
 2     private Printer p;
 3     
 4     
 5     public NumberPrinter(Printer p) {
 6     super();
 7     this.p = p;
 8     }
 9 
10 
11     @Override
12     public void run() {
13         for(int i=1; i<=52; i++) {
14             p.print(i);
15         }
16     }
17     
18 }
View Code

 

5) 编写打印字母的线程 LetterPrinter 继承 Thread 类,声明私有属性 private Printer p;在构造方法中进行赋值,实现父类的run 方法,调用 Printer 类中的输出字母的方法。

 1 public class LeeterPrinter extends Thread{
 2     private Printer p;
 3 
 4     public LeeterPrinter(Printer p) {
 5         super();
 6         this.p = p;
 7     }
 8 
 9     @Override
10     public void run() {
11         for(char c='A'; c<='Z'; c++) {
12             p.print(c);
13         }
14     }
15     
16 }
View Code

 

6) 编写测试类 Test,创建打印类对象,创建两个线程类对象,启动线程。

 1 public class Test { //测试类
 2     public static void main(String[] args) {
 3         //1创建打印类对象
 4         Printer p= new Printer();
 5         //2创建两个线程类对象
 6         NumberPrinter pi = new NumberPrinter(p);
 7         LeeterPrinter pc = new LeeterPrinter(p);
 8         //3启动线程
 9         pi.start();
10         pc.start();
11     }
12 }
View Code

运行结果

12A34B56C78D910E1112F1314G1516H1718I1920J2122K2324L2526M2728N2930O3132P3334Q3536R3738S3940T4142U4344V4546W4748X4950Y5152Z

 

posted @ 2019-05-07 14:02  北风吹沙  阅读(131)  评论(0编辑  收藏  举报