线程并发学习----Thread、Runnable、Callable

线程并发学习

线程并发学习—-核心概念(转载)
线程并发学习—-线程阻塞(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.csdn.net/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;
        }
    }

参考资料

http://blog.csdn.net/pcceo1/article/details/52444730

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值