线程并发学习
线程并发学习—-核心概念(转载)
线程并发学习—-线程阻塞(sleep、wait、notifyAll、notify、join)
线程并发学习—-线程阻塞(synchronized)
线程并发学习—-线程阻塞(lock)
线程并发学习—-Thread、Runnable、Callable
线程并发学习—-队列(Queue)
spring学习—-线程池
java中一些锁概念整理(转载)
线程简介
线程状态转换图(网上load)
线程状态介绍
- 新建状态(New):新创建了一个线程对象。
- 就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。
- 运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。
阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。
阻塞的情况分三种:
(一)、等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。
(二)、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
(三)、其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
java中多线程实现
继承Thread
例子
//继承Thread类
public class ThreadDemo extends Thread{
//实现Thread类run方法
@Override
public void run(){
System.out.println("这是线程的run方法");
}
public static void main(String[] args) {
ThreadDemo threadDemo = new ThreadDemo();
//启动线程,为什么是start 不是run见源码
threadDemo.start();
}
}
实现Runnable
例子
public class RunnableDemo implements Runnable {
@Override
public void run() {
System.out.println("这是实现Runnable的run方法1");
}
public static void main(String[] args) {
//实现Runnable接口实现
new Thread(new RunnableDemo()).start();
//匿名内部类实现
new Thread(new Runnable(){
@Override
public void run() {
System.out.println("这是实现Runnable的run方法2");
}
}).start();
}
}
实现Callable
例子
public class CallableDemo implements Callable<String>{
@Override
public String call() throws Exception {
System.out.println("这是Callable的call方法");
return "success";
}
public static void main(String[] args) throws Exception{
CallableDemo callableDemo = new CallableDemo();
ExecutorService exec = Executors.newCachedThreadPool();
ArrayList<Future<String>> results = new ArrayList(); //Future 相当于是用来存放Executor执行的结果的一种容器
for (int i = 0; i < 10; i++) {
results.add(exec.submit(new CallableDemo()));
}
for (Future<String> fs : results) {
if (fs.isDone()) {
System.out.println(fs.get());
} else {
System.out.println("Future result is not yet complete");
}
}
exec.shutdown();
}
}
三种方式分析
继承Thread实现简单,但有局限性java的类只能继承一个父类(一般不会使用)
实现接口更灵活,避免继承的局限,可以实现多个接口
实现Runnable与Callable大体一样,区别
- Runnable使用run()方法,Callable使用call()方法
- run方法没有返回值,call方法有返回值
- run不能抛出受检查异常 ,call可以抛出受检查异常。如:ClassNotFoundException
Runnable通过Thread包装实现 或者 FutureTask包装实现
Callable一般通过ExecutorService包装,本质是通过FutureTask实现
java线程类图分析
ThreadPoolExecutor的execute方法参数只能为Runnable
AbstractExecutorService的submit方法可以将Runnable和Callable包装为FutureTask,再调用execute方法
FutureTask实现RunnableFuture实现Runnable接口
ThreadPoolExecutor的execute方法,addWorker—》Worker—》默认使用DefaultThreadFactory—》new Thread—》执行start方法启动线程,执行FutureTask的run方法
详情见http://blog.youkuaiyun.com/eos2009/article/details/78617618的源码 AbstractExecutorService
自己的理解:java线程的本质 Thread 的start创建线程,执行run方法实现
源码
Thread
//Thread 实现Runnable接口
public class Thread implements Runnable {
public synchronized void start() {
if (threadStatus != 0)
throw new IllegalThreadStateException();
group.add(this);
boolean started = false;
try {
//通过调用底层start0方法创建执行线程
start0();
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}
//操作系统底层函数
private native void start0();
FutureTask
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW; // ensure visibility of callable
}
//将runnable任务包装为callable 使其有返回值 使用Executors工具类
public FutureTask(Runnable runnable, V result) {
this.callable = Executors.callable(runnable, result);
this.state = NEW; // ensure visibility of callable
}
Executors
//
public static <T> Callable<T> callable(Runnable task, T result) {
if (task == null)
throw new NullPointerException();
return new RunnableAdapter<T>(task, result);
}
static final class RunnableAdapter<T> implements Callable<T> {
final Runnable task;
final T result;
RunnableAdapter(Runnable task, T result) {
this.task = task;
this.result = result;
}
public T call() {
//底层实现使用Runnable接口run方法
task.run();
return result;
}
}