文章标题

xiaoxiao2021-02-28  98

JAVA多线程实现的三种方式

<div class="article_manage clearfix"> <div class="article_l"> <span class="link_categories"> 标签: <a href="http://www.csdn.net/tag/java" target="_blank" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_tag']);">java</a><a href="http://www.csdn.net/tag/多线程" target="_blank" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_tag']);">多线程</a> </span> </div> <div class="article_r"> <span class="link_postdate">2016-07-20 21:56</span> <span class="link_view" title="阅读次数">3724人阅读</span> <span class="link_comments" title="评论次数"> <a href="#comments" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_pinglun'])">评论</a>(0)</span> <span class="link_collect tracking-ad" data-mod="popu_171"> <a href="javascript:void(0);" onclick="javascript:collectArticle('JAVA多线程实现的三种方式','51972820');return false;" title="收藏" target="_blank">收藏</a></span> <span class="link_report"> <a href="#report" onclick="javascript:report(51972820,2);return false;" title="举报">举报</a></span> </div> </div> <style type="text/css"> .embody{ padding:10px 10px 10px; margin:0 -20px; border-bottom:solid 1px #ededed; } .embody_b{ margin:0 ; padding:10px 0; } .embody .embody_t,.embody .embody_c{ display: inline-block; margin-right:10px; } .embody_t{ font-size: 12px; color:#999; } .embody_c{ font-size: 12px; } .embody_c img,.embody_c em{ display: inline-block; vertical-align: middle; } .embody_c img{ width:30px; height:30px; } .embody_c em{ margin: 0 20px 0 10px; color:#333; font-style: normal; } </style> <script type="text/javascript"> $(function () { try { var lib = eval("("+$("#lib").attr("value")+")"); var html = ""; if (lib.err == 0) { $.each(lib.data, function (i) { var obj = lib.data[i]; //html += '<img src="' + obj.logo + '"/>' + obj.name + "  "; html += ' <a href="' + obj.url + '" target="_blank">'; html += ' <img src="' + obj.logo + '">'; html += ' <em><b>' + obj.name + '</b></em>'; html += ' </a>'; }); if (html != "") { setTimeout(function () { $("#lib").html(html); $("#embody").show(); }, 100); } } } catch (err) { } }); </script> <div class="category clearfix"> <div class="category_l"> <img src="http://static.blog.csdn.net/images/category_icon.jpg"> <span>分类:</span> </div> <div class="category_r"> <label onclick="GetCategoryArticles('6119189','mccand1234','top','51972820');"> <span onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_fenlei']);">java<em>(56)</em></span> <img class="arrow-down" src="http://static.blog.csdn.net/images/arrow_triangle _down.jpg" style="display:inline;"> <img class="arrow-up" src="http://static.blog.csdn.net/images/arrow_triangle_up.jpg" style="display:none;"> <div class="subItem"> <div class="subItem_t"><a href="http://blog.csdn.net/mccand1234/article/category/6119189" target="_blank">作者同类文章</a><i class="J_close">X</i></div> <ul class="subItem_l" id="top_6119189"> </ul> </div> </label> </div> </div>

目录(?)[+]

继承Thread类实现多线程实现Runnable接口方式实现多线程Thread本质上也是实现了Runnable接口的一个实例使用ExecutorServiceCallableFuture实现有返回结果的多线程实例可忽略

Java多线程实现方式主要有三种:继承Thread类、实现Runnable接口、使用ExecutorService、Callable、Future实现有返回结果的多线程。其中前两种方式线程执行完后都没有返回值,只有最后一种是带返回值的。

继承Thread类实现多线程

继承Thread类的方法尽管被我列为一种多线程实现方式,但Thread本质上也是实现了Runnable接口的一个实例,它代表一个线程的实例,并且,启动线程的唯一方法就是通过Thread类的start()实例方法。start()方法是一个native方法,它将启动一个新线程,并执行run()方法。这种方式实现多线程很简单,通过自己的类直接extend Thread,并复写run()方法,就可以启动新线程并执行自己定义的run()方法。例如:

public class MyThread extends Thread {   public void run() {    System.out.println("MyThread.run()");   } } 12345 12345

在合适的地方启动线程如下:

MyThread myThread1 = new MyThread(); MyThread myThread2 = new MyThread(); myThread1.start(); myThread2.start(); 1234 1234

实现Runnable接口方式实现多线程(Thread本质上也是实现了Runnable接口的一个实例)

如果自己的类已经extends另一个类,就无法直接extends Thread(java类的单继承,接口可以多继承),此时,必须实现一个Runnable接口,如下:

public class MyThread extends OtherClass implements Runnable {   public void run() {    System.out.println("MyThread.run()");   } } 12345 12345

为了启动MyThread,需要首先实例化一个Thread,并传入自己的MyThread实例:

MyThread myThread = new MyThread(); Thread thread = new Thread(myThread); thread.start(); 123 123

事实上,当传入一个Runnable target参数给Thread后,Thread的run()方法就会调用target.run(),参考JDK源代码(Thread的run方法的实现):

public void run() {   if (target != null) {    target.run();   } } 12345 12345

使用ExecutorService、Callable、Future实现有返回结果的多线程

ExecutorService、Callable、Future这个对象实际上都是属于Executor框架中的功能类。想要详细了解Executor框架的可以访问http://www.javaeye.com/topic/366591。返回结果的线程是在JDK1.5中引入的新特征,确实很实用,有了这种特征我就不需要再为了得到返回值而大费周折。可返回值的任务必须实现Callable接口,类似的,无返回值的任务必须Runnable接口。执行Callable任务后,可以获取一个Future的对象,在该对象上调用get就可以获取到Callable任务返回的Object了,再结合线程池接口ExecutorService就可以实现传说中有返回结果的多线程了。下面提供了一个完整的有返回结果的多线程测试例子,在JDK1.5下验证过没问题可以直接使用。代码如下:

import java.util.concurrent.*; import java.util.Date; import java.util.List; import java.util.ArrayList; /** * 有返回值的线程 */ @SuppressWarnings("unchecked") public class Test { public static void main(String[] args) throws ExecutionException, InterruptedException { System.out.println("----程序开始运行----"); Date date1 = new Date(); int taskSize = 5; // 创建一个线程池 ExecutorService pool = Executors.newFixedThreadPool(taskSize); // 创建多个有返回值的任务 List<Future> list = new ArrayList<Future>(); for (int i = 0; i < taskSize; i++) { Callable c = new MyCallable(i + " "); // 执行任务并获取Future对象 Future f = pool.submit(c); //call方法的返回结果输出 f.get().toString() // System.out.println(">>>" + f.get().toString()); list.add(f); } // 关闭线程池 pool.shutdown(); // 获取所有并发任务的运行结果 for (Future f : list) { // 从Future对象上获取任务的返回值,并输出到控制台 System.out.println(">>>" + f.get().toString()); } Date date2 = new Date(); System.out.println("----程序结束运行----,程序运行时间【" + (date2.getTime() - date1.getTime()) + "毫秒】"); } } class MyCallable implements Callable<Object> { private String taskNum; MyCallable(String taskNum) { this.taskNum = taskNum; } public Object call() throws Exception { System.out.println(">>>" + taskNum + "任务启动"); Date dateTmp1 = new Date(); Thread.sleep(1000); Date dateTmp2 = new Date(); long time = dateTmp2.getTime() - dateTmp1.getTime(); System.out.println(">>>" + taskNum + "任务终止"); return taskNum + "任务返回运行结果,当前任务时间【" + time + "毫秒】"; } } 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960

运行结果

代码说明: 上述代码中Executors类,提供了一系列工厂方法用于创先线程池,返回的线程池都实现了ExecutorService接口。

public static ExecutorService newFixedThreadPool(int nThreads) 1 1

创建固定数目线程的线程池。

public static ExecutorService newCachedThreadPool() 1 1

创建一个可缓存的线程池,调用execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。

public static ExecutorService newSingleThreadExecutor() 1 1

创建一个单线程化的Executor。

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) 1 1

创建一个支持定时及周期性的任务执行的线程池,多数情况下可用来替代Timer类。

ExecutoreService提供了submit()方法,传递一个Callable,或Runnable,返回Future。如果Executor后台线程池还没有完成Callable的计算,这调用返回Future对象的get()方法,会阻塞直到计算完成。

实例(可忽略):

public List<Integer> setShopType(List<Integer> shopIDs, int bizID, int shopType, int operatorID) { //1.根据shopIds找到相应的轮转组Ids. //2.根据轮转组Id找到本轮转组下面的所有shopId for(Integer shopId:shopIDs){ Response res = rotateService.initRotateGroupWithoutBizValidate(shopId,bizID); if(!res.isSuccess()){ throw new ApplicationException(res.getComment()); } } List<RotateGroupDTO> rotateGroupDTOs = rotateGroupService.getRotateGroup(bizID, shopIDs); //3.更新所有的shopId的type List<Integer> rotateGroupIDs = Lists.transform(rotateGroupDTOs, new Function<RotateGroupDTO, Integer>() { @Override public Integer apply(RotateGroupDTO input) { return input.getId(); } }); //prepare for log Map<Integer, List<RotateGroupShopDTO>> rotateGroupShopMap = rotateGroupShopService.getRotateGroupShop(rotateGroupIDs); List<RotateGroupShopDTO> rotateGroupShopDTOList = Lists.newArrayList(); for (Integer rotateGroupId : rotateGroupShopMap.keySet()) { rotateGroupShopDTOList.addAll(rotateGroupShopMap.get(rotateGroupId)); } List<Integer> shopIdList = Lists.transform(rotateGroupShopDTOList, new Function<RotateGroupShopDTO, Integer>() { @Override public Integer apply(RotateGroupShopDTO input) { return input.getShopID(); } }); ShopHistoryModel model = ShopHistoryModel.builder().shopIdList(shopIdList).bizId(bizID).shopHistoryType(SubActionTypeEnum.VIP_MARK.getCode()).build(); Map<Integer, Integer> oldValue = (Map<Integer, Integer>) bigCustomerProcessor.getData(model); //execute Response<Boolean> response = rotateService.setRotateGroupBigCustomer(rotateGroupIDs, bizID, shopType); //compare and create log Map<Integer, Integer> newValue = (Map<Integer, Integer>) bigCustomerProcessor.getData(model); if (response.isSuccess()) { bigCustomerProcessor.compareAndCreateLog(model, oldValue, newValue,operatorID); return null; } return shopIDs; } @Override public List<Integer> batchSetShopType(List<Integer> shopIDs, final int bizID, final int shopType, final int operatorID) throws Exception { //初始化线程池 String threadSize = LionConfigUtils.getProperty("roc-operation-tools-pc-web.threadSize", "50"); ExecutorService executorService = Executors.newFixedThreadPool(Integer.parseInt(threadSize)); //初始化处理失败的集合 List<Integer> wrongList = Lists.newArrayList(); //tasks List<Callable<List<Integer>>> tasks = Lists.newArrayList(); String batchSize = LionConfigUtils.getProperty("roc-operation-tools-pc-web.batchSize", "200"); List<List<Integer>> batchShopsList = Lists.partition(shopIDs, Integer.parseInt(batchSize)); for (final List<Integer> shopids : batchShopsList) { tasks.add(new Callable<List<Integer>>() { @Override public List<Integer> call() throws Exception { return setShopType(shopids, bizID, shopType, operatorID); } }); } //futures 时间监控 invokeAll 之前 Stopwatch stopwatch = Stopwatch.createStarted(); List<Future<List<Integer>>> futures = executorService.invokeAll(tasks); for (Future<List<Integer>> future : futures) { while (true) { if (future.isDone() && !future.isCancelled()) { if(CollectionUtils.isNotEmpty(future.get())){ //返回的结果添加进去 wrongList.addAll(future.get()); } break; } } } log.info("batchSetShopType cost time:" + stopwatch.elapsed(TimeUnit.MILLISECONDS) + "ms"); //关闭线程池 executorService.shutdown(); return wrongList; } 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192

参考: http://blog.csdn.net/aboy123/article/details/38307539 http://www.iteye.com/topic/366591 http://mars914.iteye.com/blog/1508429 http://www.cnblogs.com/gw811/archive/2012/10/15/2724602.html

(function () {('pre.prettyprint code').each(function () { var lines = (this).text().split(\n).length;var numbering = $(' ').addClass('pre-numbering').hide(); (this).addClass(hasnumbering).parent().append( numbering); for (i = 1; i
转载请注明原文地址: https://www.6miu.com/read-47591.html

最新回复(0)