《Java知识点总结系列》第十三章线程篇.docx
《《Java知识点总结系列》第十三章线程篇.docx》由会员分享,可在线阅读,更多相关《《Java知识点总结系列》第十三章线程篇.docx(15页珍藏版)》请在冰点文库上搜索。
《Java知识点总结系列》第十三章线程篇
知识点预览
线程的概念
线程的开发
线程的状态
线程的同步
wait与notify
1. 线程的概念
在一个程序中同时运行的多个独立流程,每一个独立的流程就是一个线程。
2. 线程的三要素:
CPUCodeData
3.线程并发
同一时间多个线程同时执行
多个线程:
轮流使用CPU,有先后顺序,
短暂时间:
CPU时间片
人的反映时间远大于CPU时间片:
认为线程同时执行
4.主线程
main方法代表主线程
线程的开发
1.继承Thread类与实现Runnable接口两种方式
2. 继承Thread类开发线程
a) 用户定义一个类继承Thread类
b)覆盖run方法
c)运行线程//start启动线程
3.思考
[java] viewplaincopy
1.package chp13.ex01;
2.
3./**
4. *
5. * @Author:
Wentasy
6. * @FullName:
TestThread.java
7. * @Description:
线程的创建
8. * @Create Date:
2012-8-17
9. */
10.class MyThread1 extends Thread{
11. public void run(){
12. for(int i = 1; i<=1000; i++){
13. System.out.println(i + " $$$");
14. }
15. }
16.}
17.
18.class MyThread2 extends Thread{
19. public void run(){
20. for(int i = 1; i<=1000; i++){
21. System.out.println(i + " ###");
22. }
23. }
24.}
25.public class TestThread{
26. public static void main(String args[]){
27. Thread t1 = new MyThread1();
28. Thread t2 = new MyThread2();
29.
30. //启动线程
31. t1.start();
32. t2.start();
33. }
34.}
a)程序的输出结果固定吗?
不是运行需要CPU分配时间片
b) 程序中存在几个线程?
程序的先后顺序
3个线程(t1,t2,主线程)没有关系独立的
main----->t1、t2、main(无顺序竞争关系谁先执行完不确定)
c)可不可以直接在main方法中直接调用run()
不可以,主线程调用run后,不是3个线程,只有一个主线程,相当于调用方法,线程没有启动。
4. Runnable接口开发线程
a)用户开发一个类实现Runnable接口
b)实现run()
c)运行线程
Runnabletarget=newMyRunnable2();
Threadt2=newThread(target);
5.两种建立线程方式的比较
a)继承Thread是面向对象的编程方式
b) 实现Runnable接口解决了单一继承限制
线程的状态
1.Threada=newThread();a.start();
a)初始状态:
创建了线程对象
b)可运行状态:
调用完了start()
c)运行状态:
可运行状态下的线程获得CPU时间片
d)终结状态:
run方法内容全部执行完
2. sleep与阻塞
阻塞状态
3.sleep方法(Thread定义)
a)publicstaticvoidsleep(longmillis)throwsInterruptedException
//longmillis:
睡多少毫秒
//InterruptedException:
检查异常
b)利用sleep()方法对线程的控制是非常不精确的。
4.join方法
a)join方法法也会导致线程阻塞
b)特点:
如果当前线程中调用了另外一个线程的join方法,当前线程会立即阻塞着,直到另外一个线程运行完成。
c) join方法的问题:
i. 如果2个线程调用对方的join方法会导致程序无法运行
ii. 解决办法:
publicfinalvoidjoin(longmillis)throwsInterruptedException
//重载方法
//参数为long类型往往代表毫秒
//不管是否运行完,阻塞------>可运行
线程同步
1.应用数组实现一个栈
[java] viewplaincopy
1.package chp13.ex05;
2.
3./**
4. *
5. * @Author:
Wentasy
6. * @FullName:
TestMyStack.java
7. * @Description:
用数组实现一个栈
8. * @Create Date:
2012-8-17
9. */
10.class MyStack{
11. char[] data = {'A', 'B', ' '};
12. int index = 2;
13. public void push(char ch){
14. data[index] = ch;
15. index ++;
16. }
17. public void pop(){
18. index --;
19. data[index] = ' ';
20. }
21. public void print(){
22. for(int i = 0; i23. System.out.print(data[i] + "\t");
24. }
25. System.out.println();
26. }
27.}
28.
29.
30.public class TestMyStack{
31. public static void main(String args[]){
32. MyStack ms = new MyStack();
33. ms.push('C');
34. ms.print();// A B C
35. ms.pop();
36. ms.print();// A B
37. }
38.}
a)pop:
弹出
b)push:
压入
c)代码实现没有问题
d)改动的MyStack中的push方法Sleep
e) 改写代码提供两个线程一个存值一个取值
f) 数据不一致
2.产生数据不一致原因
多个线程并发访问了同一个对象,如果破坏了不可分割的操作,从而就会造成数据不一致。
3.临界资源
被多个线程并发访问的对象
4.原子操作
不可分割的操作
5.线程不安全的对象
被多个线程并发访问时,如果一个对象有可能出现数据不一致的问题,那么这个对象称为线程不安全对象 ArrayList:
线程不安全 Vector:
线程安全
6.如何解决多线程并发访问的问题
synchronized(object){
代码块
//object:
任何对象
}
互斥锁标志:
每个对象都有
synchronized(this)(使用当前对象的互斥锁标志)
synchronized修饰方法(使用当前对象的互斥锁标志)
7. synchronized注意
a) 对象互斥锁标志是与对象挂钩的
[java] viewplaincopy
1.synchronized(obj1){
2. 代码块1;
3.}
4.
5.synchronized(obj1){
6. 代码块2;
7.}
8.
9.synchronized(obj2){
10. 代码块3;
11.}
b) 死锁
[java] viewplaincopy
1.synchronized(a){
2. ...//1
3. synchronized(b){
4.
5. }
6.}
7.
8.synchronized(b){
9. ...//2
10. synchronized(a){
11.
12. }
13.}
wait与notify(Object)
1. 用于解决死锁
[java] viewplaincopy
1.synchronized(a){
2. ...//1
3. a.wait();
4. synchronized(b){
5.
6. }
7.}
8.
9.synchronized(b){
10. ...//2
11. synchronized(a){
12. a.notify();
13. }
14.}
2. 线程通信
生产者和消费者问题
同时两个线程操作一个栈,一个线程负责往栈中添加数据,另一个线程负责从栈中删除数据。
[java] viewplaincopy
1.package chp13.ex09;
2.
3./**
4. *
5. * @Author:
Wentasy
6. * @FullName:
TestProducerConsumer.java
7. * @Description:
线程通信:
生产者和消费者问题
8. * @Create Date:
2012-8-17
9. */
10.public class TestProducerConsumer {
11. public static void main(String[] args) {
12. Stack s=new Stack();
13. Thread t1=new Producer(s);
14. Thread t2=new Consumer(s);
15. t1.start();
16. t2.start();
17. }
18.}
19.class Stack{
20. private char[] data=new char[6];
21. private int index=0;
22. private void print(){
23. for(int i=0;i24. System.out.print(data[i]+" ");
25. }
26. System.out.println();
27. }
28. public synchronized void push(char c){
29. while(index==data.length){
30. try {
31. this.wait();
32. } catch (InterruptedException e) {}
33. }
34. data[index]=c;
35. index++;
36. this.notifyAll();
37. System.out.print(c+" push stack:
");
38. print();
39. }
40.
41.
42. public synchronized void pop(){
43. while(index==0){
44. try {
45. this.wait();
46. } catch (InterruptedException e) {}
47. }
48. index--;
49. char c=data[index];
50. data[index]=' ';
51. this.notifyAll();
52. System.out.print(c+" poped stack:
");
53. print();
54. }
55.}
56.class Producer extends Thread{
57. Stack s;
58. public Producer(Stack s) {
59. this.s = s;
60. }
61. public void run(){
62. for(char c='A';c<='Z';c++){
63. s.push(c);
64. try {
65. Thread.sleep(50);
66. } catch (InterruptedException e) {
67. e.printStackTrace();
68. }
69. }
70. }
71.}
72.class Consumer extends Thread{
73. Stack s;
74. public Consumer(Stack s) {
75. this.s = s;
76. }
77. public void run(){
78. for(int i=1;i<=26;i++){
79. s.pop();
80. try {
81. Thread.sleep(100);
82. } catch (InterruptedException e) {
83. e.printStackTrace();
84. }
85. }
86. }
87.}