线程基础学习
来源:互联网 发布:cad珠宝设计软件 编辑:程序博客网 时间:2024/06/06 12:33
github地址:https://github.com/liujinjin777/liujinjintest.git
讲解流程为:线程状态 -》实现线程的几种方法 -》线程基本方法和关键字 -》问答时刻
线程状态
图来自:http://blog.csdn.net/huang_xw/article/details/7316354
新建、准备/就绪、运行、阻塞、死亡
阻塞:1,等待阻塞,运行线程调用wait方法进入等待池【wait和sleep,wait会释放锁】
2,同步阻塞,就绪状态线程准备获取锁的时候,已经有其他线程占领了,这个时候就进入锁池中。
3,其他阻塞,运行线程调用sleep或者join或者io请求,进入阻塞状态。当sleep结束join线程结束io处理完毕,线程重新进入就绪状态。
Thread类源码状态
public enum State { NEW, // 新建 RUNNABLE, // 运行 BLOCKED, // 锁阻塞 WAITING, // 等待阻塞(不带有超时值) TIMED_WAITING, // 等待阻塞(带有超时值) TERMINATED; // 终止}
实现线程的三种方法
其实按照原理来分的话是2种,实现runnable或者callable
1.实现runnable接口,实现run方法。
Thread thread = new Thread(Runable runable);thread.start();
代码实现:把runnable记录成为Thread的成员变量target 。调用run的时候,直接调用
@Overridepublic void run() { if (target != null) { target.run(); }}
2.继承Thread类,重写run方法。
Thread myThread = new MyThread();myThread.start();
3.利用callable接口,重写call方法。
public class MyCallable implements Callable { private int flag = 0; public MyCallable(int flag){ this.flag = flag; } public String call() throws Exception{ if (this.flag == 0){ System.out.println("call flag = 1"); return "flag = 0"; } if (this.flag == 1){ try { while (true) { System.out.println("looping."); Thread.sleep(2000); } } catch (InterruptedException e) { System.out.println("Interrupted"); } return "false"; } else { System.out.println("Bad flag value!"); throw new Exception("Bad flag value!"); } }}
//-------- 第1种写法,类似重写runable接口MyCallable task1 = new MyCallable(0);MyCallable task2 = new MyCallable(2);FutureTask<MyCallable> oneTask1 = new FutureTask<MyCallable>(task1);FutureTask<MyCallable> oneTask2 = new FutureTask<MyCallable>(task2);Thread thread = new Thread(oneTask1);Thread thread2 = new Thread(oneTask2);thread.start();thread2.start();//-------- 第2种MyCallable task1 = new MyCallable(0);MyCallable task2 = new MyCallable(1);MyCallable task3 = new MyCallable(2);ExecutorService es = Executors.newFixedThreadPool(3);try { // 提交并执行任务,任务启动时返回了一个Future对象, // 如果想得到任务执行的结果或者是异常可对这个Future对象进行操作 Future future1 = es.submit(task1); // 获得第一个任务的结果,如果调用get方法,当前线程会等待任务执行完毕后才往下执行 System.out.println("task1: " + future1.get()); Future future2 = es.submit(task2); // 等待5秒后,再停止第二个任务。因为第二个任务进行的是无限循环 Thread.sleep(5000); System.out.println("task2 cancel: " + future2.cancel(true)); // 获取第三个任务的输出,因为执行第三个任务会引起异常 // 所以下面的语句将引起异常的抛出 Future future3 = es.submit(task3); System.out.println("task3: " + future3.get());} catch (Exception e){ System.out.println(e.toString());}// 停止任务执行服务es.shutdownNow();
callable与runable的差别
1,重写call方法和重写run方法
2,可以有返回值
3,可以抛出异常
线程基本方法和关键字
start、sleep、join 、yeild、run、wait、notify、notifyAll、interrupt、synchronized、volatile
start:启动一个线程。会调用run方法。
sleep:睡眠一个线程。睡眠期间不会释放锁。【com.liujinjin.myThread.testSleep】
join:当前线程会等待调用join线程运行后运行。【com.liujinjin.myThread.testJoin】
yeid:让步线程。尽可能(不绝对)让优先级高的执行 。【com.liujinjin.myThread.testYield】
每个线程都有自己的执行级别,范围是1-10,默认为5。通过setPriority方法更改。
run:与start配合使用,如果直接调用和普通方法是一样的。
wait : 等待线程。等待期间释放锁,调用前需要获得调用对象锁。【com.liujinjin.myThread.testWait】
notify : 唤醒线程。与wait方法联合使用,调用前需要获得对象锁。调用后不释放锁。【com.liujinjin.myThread.testnotify2】
notifyAll :与notify类似,唤醒所有wait线程。
interrupt : 不会中断一个线程。而是当线程被阻塞(wait,join,sleep)时,一种停止阻塞的方法。【com.liujinjin.myThread.testInterrupt】
类
Object:wait、notify、notifyAll
Thread:start、sleep、join 、yeild 、interrupt
Runnale:run
关键字:synchronized、volatile
native修饰:wait、notify、notifyAll、start0、sleep、yeild、interrupt0
非native修饰:join、run
synchronized修饰:start、join
static修饰:sleep
问答
1.什么时候需要考虑线程安全问题?
当使用变量为成员变量的时候。方法内定义的变量无线程问题。
2.线程可以重复启动吗?
不可以,在start的时候会检查线程状态,如果不为0会 throw IllegalThreadStateException。
2.1那么线程池是如何做的?
待调研
3.线程的底层是通过cpu时间分片来实现的,串行化随机分给每个线程时间片。为什么这样会比单线程快?
4.线程的优点和缺点
5.volitle为何不能保证线程安全?
其底层实现原理,在汇编语言加了lock前缀,实现的功能是
1)在处理器中运算的变量改变后,立刻刷回主线程。
2)主线程里的变量被修改之后,失效其他处理器内的变量值。
一个加法操作。
1)从主线程读取变量值到处理器。
2)更改值。
3)刷回主线程。
6.为什么wait、notify、notifyAll等方法放在object类里,而不是thread类里?
1,wait、notify是sychnized修饰的,调用的前提是获取到当前对象的锁,而锁是这个对象本身。如果是放在thread里,每个对象的锁是当前的thread对象,其他线程调用的时候需要先获取到之前wait线程对象锁。不直观,复杂。
2,可以让object类和子类使用成为锁。
- 线程学习一:线程基础
- java线程学习基础
- 线程基础学习
- 线程的基础学习之创建线程
- 基础学习总结之线程
- java基础学习—线程
- JAVA基础学习之多线程
- j2se学习笔记-线程基础
- Java基础学习之多线程
- java基础学习之线程
- java基础学习之多线程
- 多线程学习笔记 线程基础
- 线程学习——基础
- Java基础学习之线程
- JAVA基础学习之线程
- java 基础学习-04 线程学习案例
- 多线程基础学习五:线程池基础学习
- linux多线程学习(一)---线程基础
- POJ 1061青蛙的约会(欧几里德扩展)
- Android成长之路-BaseExpandableListAdapter的用法
- Android 中DataBinding的使用及数据的绑定
- 31. Next Permutation(C++)
- EditText右下角实时显示输入字数
- 线程基础学习
- PHP接入阿里云市场 阿里短信服务DEMO
- Scala学习笔记(三)scala的函数式编程
- TensorFlow 中的交叉熵(Cross Entropy)
- 神经网络的交叉熵损失函数
- android 获取系统默认路径
- P2P在IPTV中解决数据服务器传输瓶颈
- Python概念-上下文管理协议中的__enter__和__exit__
- UVA-340 Master-Mind Hints