汕头网站建设方法港北网站建设
web/
2025/10/4 9:30:13/
文章来源:
汕头网站建设方法,港北网站建设,企业做国际站哪个网站好,做网站菏泽作者简介#xff1a;大家好#xff0c;我是smart哥#xff0c;前中兴通讯、美团架构师#xff0c;现某互联网公司CTO 联系qq#xff1a;184480602#xff0c;加我进群#xff0c;大家一起学习#xff0c;一起进步#xff0c;一起对抗互联网寒冬 多线程向来是面试的重灾…作者简介大家好我是smart哥前中兴通讯、美团架构师现某互联网公司CTO 联系qq184480602加我进群大家一起学习一起进步一起对抗互联网寒冬 多线程向来是面试的重灾区它真的很难。一般来说普通的开发人员很少有机会能直接写多线程一般都是使用封装好的工具类或者JDK提供的API但并不意味着我们可以不用了解多线程。 学习多线程的好处至少有两点
应付面试深入理解并发编程帮助我们更好地使用JDK提供的锁及JUC工具包 今天我们再来强化一下多线程的基础知识。 线程类与任务类
我在初学多线程时也感到云里雾里后来才发现自己一开始就把一些概念搞错了很多博客或者视频每次都会说“实现”多线程的方式有3种Thread、Runnable和Callable其实我个人是不太认同这种说法的。Thread是线程类另外两个是任务类不是一类事物啊 也即是说JDK看似提供了很多和多线程相关的类实际上有且仅有Thread类能通过start0()方法向操作系统申请线程资源本地方法。 线程池只是对Thread的复用两者本质上可以归为一类这里暂且不讨论 另外JVM的线程和操作系统的线程是一一对应的当我们new一个Thread对象并调用start()方法后JVM的Thread对象就与系统底层的一个线程资源绑定了。 而Runnable和Callable并不会产生线程仅仅用于包裹待执行的任务。如果没有线程或线程池去执行它们只不过是一坨普通的代码。 为了让Thread和Runnable/Callable产生关联通常需要我们手动进行“组合”Thread只能接收RunnableCallable要使用线程池后面再介绍
new Thread(() - {// 把任务包裹在Runnable任务类中通过构造参数传入ThreadSystem.out.println(待执行任务);
}).start();
但实际开发中大家肯定也见过这种写法
new Thread() {Overridepublic void run() {// 直接重写Thread的run()把待执行的任务放里面System.out.println(待执行任务);}
}.start();
注意上面这种写法可不是传入Runnable/Callable而是采用匿名类的方式重写了Thread自己的run()。 总结一下要想让多线程执行一个任务大致有以下几种做法
线程与任务不分离 重写Thread的run()把任务直接塞到Thread内部执行路径是JVM线程--Thread#run()
线程与任务分离推荐 把任务塞到Runnable丢入Thread里执行路径是JVM线程--Thread#run()--target.run()把任务塞到Runnable/Callable丢到线程池里屏蔽内部细节省心省力 注意当Thread#start()向操作系统申请线程后线程的执行入口始终是Thread#run()而不是Runnable/Callable的run() 到这里我们替大家扫清了一些繁杂的概念只需记住Java创建多线程有且仅有一种方式Thread无论是直接通过new Thread().start()或是通过线程池底层其实都是Thread在向操作系统申请资源而且新线程启动后会找到原来的Thread从它的run()方法开始执行。 任务代码是如何被执行到的
上面提到过如果需要多线程帮我们执行任务一般有3种方式
重写Thread#run()将任务包装成Runnable丢入Thread将任务包装成Runnable/Callable丢入线程池 那么为什么我把代码放在这些指定的地方线程就能执行到呢 其实代码的执行顺序说到底也是人为设计、编排的只不过Thread、线程池等设计得更为精妙。整个过程就像一条流水线从上游到下游我们只要把商品放入指定的地方最终就会被封口、打包并装箱。 这里主要介绍方式1、2的原理线程池的执行原理后面会介绍。Thread是如何执行任务的呢关键在于Thread#run() Thread#start()的作用是向操作系统申请线程资源当操作系统分配好线程资源并且当前线程得到CPU执行权时执行的入口一定是Thread#run()。 那么线程执行run()时会发生什么呢
如果我们重写了Thread#run()就会执行我们重写的方法任务和线程不分离如果我们没有重写Thread#run() target为nullrun()为空直接结束target不为null就会执行target的run()。而target就是我们通过Thread构造器传入的Runnable对象 所以如果不重写Thread#run()就一定要传入任务类target否则新建的Thread无任务可执行就浪费了 最后再来回顾一下让线程执行指定任务的几种常见方式
public class AsyncAndWaitTest {public static void main(String[] args) throws ExecutionException, InterruptedException {// 方式1重写Thread#run()Thread thread new Thread() {Overridepublic void run() {System.out.println(Thread.currentThread().getName() 正在执行);}};thread.start();// 方式2构造方法传入Runnable实例new Thread(() - {System.out.println(Thread.currentThread().getName() 正在执行);}).start();// 方式3线程池 Callable/Runnable这里以Callable为例ExecutorService executorService Executors.newSingleThreadExecutor();FutureString submit executorService.submit(() - {System.out.println(Thread.currentThread().getName() 正在执行);Thread.sleep(3 * 1000L);return success;});String result submit.get();System.out.println(result result);// 关闭线程池executorService.shutdown();}
} 除了上面3种利用多线程执行任务的方式我们再另外介绍一种初学者可能觉得有点绕、但源码里经常会见到的写法算是Runnable的变种写法
把new Thread().start()隐藏到某个类的内部 重点关注Worker到底是什么以及begin()内部做了什么。不熟悉的同学不妨自己写一下琢磨一下。我们马上会在JDK的某个类中看到类似的写法 总之在我心里Thread的Level要比Runnbale、Callable高一级。看到很多人把它们混在一起不禁想起一句话
萧某大好男儿竟和你这种人齐名 --- 乔峰 作者简介大家好我是smart哥前中兴通讯、美团架构师现某互联网公司CTO 进群大家一起学习一起进步一起对抗互联网寒冬
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/86710.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!