标签:cpu call() 返回 xtend throws 法规 runnable 性能 block
目录
多线程能大幅度的提升CPU的使用率, 使得任务处理更加快速, 但是也并不是多线程一定高效, 线程的切换会涉及到CPU上下文切换, 上下文的切换会大幅度的拉低CPU的性能.
当线程对象被创建后, 即进入了新建状态. 如: Thread thread = new MyThread();
当调用线程对象的start()方法后, 线程随即进入了就绪状态. 处于就绪状态的线程, 只能说明此线程已经做好了准备, 随时等待CPU调度执行, 并不是调用了start()之后就开始执行了.
当CPU调度处于就绪状态的线程时, 线程才得以真正的执行, 随即进入了运行状态. 就绪状态是进入运行状态的唯一入口, 线程要想进入运行状态, 必须处于就绪状态.
处于运行状态的线程由于某种原因, 暂时放弃对CPU的使用权, 停止执行, 此时进入阻塞状态. 直到其进入就绪状态, 才有机会被CPU重新调度.
进入阻塞状态可能的原因:
线程执行完成后或者因为异常退出了run()方法, 则线程的生命周期结束了.
箭头(->)表示可以切换到后续状态
通过继承Thread类, 重写run()方法可以实现线程的创建.
线程执行体就是run()方法中的内容.
public class MyThread extends Thread {
@Override
public void run() {
// do something...
}
}
public class Demo {
public static void main(String[] args) {
new MyThread().start();
}
}
创建MyThread对象, 然后调用start()方法即可启动线程. 虽然线程的执行体是run()方法中的内容, 但是不能直接使用new MyThread().run();
启动线程. 这种方式启动的话就是普通方法的调用, 并不会有线程的创建.
通过实现接口, 并实现接口中的run()方法, 然后在创建Thread对象时作为参数传入即可实现线程de创建. 线程执行体也就是run()方法中的内容.
public class MyThread implements Runnable {
@Override
public void run() {
// do something...
}
}
public class Demo {
public static void main(String[] args) {
new Thread(new MyThread()).start();
}
}
两种创建方法的区别就是一个继承类, 一个是实现接口, 根据Java的语法规范可知, 继承是单继承而实现可以多实现.
打开Thread的源码可知, Thread实现了Runnable接口, 继续打开Thread的run()看到
@Override
public void run() {
if (target != null) {
target.run();
}
}
这里的target即为第二种方式传入的new MyThread()
, 如果直接使用new Thread().start();
, 结果就是创建一个线程, 但是线程没有线程执行体(没有执行代码), 随即结束线程. 因为target为null.
这种方式与使用Runnable创建类似, 但是该方式更加强大, 主要体现在两方面: 1. Callable可以抛出异常; 2. Callable可以有返回值.
并且, Callable在获取返回值的时候(调用get()方法时)会等待线程执行完成.(肯定要等待线程执行完成才能拿到返回值.)
使用:
public class MyCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
// do something...
return 10;
}
}
public class Demo {
public static void main(String[] args) throws Exception {
// 实例化对象
MyCallable callable = new MyCallable();
// 使用FutureTask封装
FutureTask<Integer> task = new FutureTask<>(callable);
// 启动线程
new Thread(task).start();
// 获取返回值, get()方法会有异常抛出
Integer integer = task.get();
}
}
如果这时你对Thread对象也可以接受FutureTask对象有疑问的话? 那么你非常棒.
打开FutureTask的源码看到他实现了RunnableFuture接口, 而RunnableFuture接口又继承了Runnable接口, 所以Thread可以接受FutureTask对象.
这时你如果能想到既然FutureTask实现了Runnable接口, 那么它的run()是如何实现的有疑问的话? 你的求知欲很强. 看看源码就知道了, 也会知道为什么需要重写call().
我们本应该就带有很强的求知欲, 去探索底层实现. 不然和机器有什么区别呢.
标签:cpu call() 返回 xtend throws 法规 runnable 性能 block
原文地址:https://www.cnblogs.com/wuqinglong/p/9765277.html