【技术交流】让我们来谈一谈多线程和并发任务
2013-12-31 15:40
211 查看
相信你已经了解过多线程的概念,不妨咱们来回顾下,做个暖场如何
相关概念线程、进程 依赖包含关系、相似(状态)、区别(内存共享、资源共享、成本)进程是操作系统分配资源的基础单位,而线程是CPU执行的基础单位。线程与线程间是并列且独立的。
线程空间、ThreadLocal、线程上下文线程运行时所占用的内存、锁、cpu等资源的一个虚拟视图线程的一个局部变量,可以理解为与当前线程绑定的一个map线程空间的一个实时状态
线程状态创建、运行、阻塞、销毁
![](https://oscdn.geek-share.com/Uploads/Images/Content/202003/16/69987e3434b2fe519110b52a6d0853d3.png)
线程与锁加锁是为了同步调度
锁的类型:共享锁、互斥锁;只读锁、可写锁
死锁
争夺资源
调度失当
线程并发模型阻塞队列当队列不满足操作条件时,操作线程将进入阻塞状态
get()时,如果队列为空,则阻塞线程,直到成功执行了add()
add()时,如果队列已满,则阻塞线程,直到成功执行了get()
最常用的一种并发调度器eg :生产者-消费者
闭锁闭锁线程转换到“开门”状态之前,任何尝试“进门”的线程都会被阻塞eg:登机
关卡所有线程都执行到“关卡”点之前,任何尝试“过关”的线程都会被阻塞eg:大巴车
线程实现java多线程实现,有两种方法。继承Thread,实现接口Runable。大多数时候我们采用后者。原因很简单:单继承,多实现,况且java的设计原则有一条是“面向接口编程”。测试类
并发任务执行器的顶级抽象,只针对Runnable
ExecutorService
对Executor进行扩展,支持Callable和Future
Callable
对Runnable进行扩展,提供了返回值。
Future
阻塞线程,直到Callable返回了值
FutureTask
实现了Callable和Future
可以简单理解为同时是生产者和消费者的类
其它
闭锁、关卡等实现
并发任务使用
声明一个ExecutorService
向ExecutorService 提交一个或多个Callable,并获取Future
从Future中获取Callable的返回结果
项目应用
实际上是一个“大巴车”模型
测试类
要注意的地方:异常处理ExecutorService有两个方法:submit、execute
that's all!如果文章中什么错误,请与我联系,也欢迎您跟我邮件交流哦!邮箱:wyc_job@163.com
本文出自 “ATIP團戰術策劃部” 博客,请务必保留此出处http://atip3.blog.51cto.com/6312771/1347150
相关概念线程、进程 依赖包含关系、相似(状态)、区别(内存共享、资源共享、成本)进程是操作系统分配资源的基础单位,而线程是CPU执行的基础单位。线程与线程间是并列且独立的。
线程空间、ThreadLocal、线程上下文线程运行时所占用的内存、锁、cpu等资源的一个虚拟视图线程的一个局部变量,可以理解为与当前线程绑定的一个map线程空间的一个实时状态
线程状态创建、运行、阻塞、销毁
![](https://oscdn.geek-share.com/Uploads/Images/Content/202003/16/69987e3434b2fe519110b52a6d0853d3.png)
线程与锁加锁是为了同步调度
锁的类型:共享锁、互斥锁;只读锁、可写锁
死锁
争夺资源
调度失当
线程并发模型阻塞队列当队列不满足操作条件时,操作线程将进入阻塞状态
get()时,如果队列为空,则阻塞线程,直到成功执行了add()
add()时,如果队列已满,则阻塞线程,直到成功执行了get()
最常用的一种并发调度器eg :生产者-消费者
闭锁闭锁线程转换到“开门”状态之前,任何尝试“进门”的线程都会被阻塞eg:登机
关卡所有线程都执行到“关卡”点之前,任何尝试“过关”的线程都会被阻塞eg:大巴车
线程实现java多线程实现,有两种方法。继承Thread,实现接口Runable。大多数时候我们采用后者。原因很简单:单继承,多实现,况且java的设计原则有一条是“面向接口编程”。测试类
public class TestMain { @Test public void testThread(){ // Thread th1 = new TestNoSynThread(); Thread th2 = new TestNoSynThread(); th1.start(); th2.start(); } @Test public void testRunable(){ // TestNoSynRunable r = new TestNoSynRunable(); Thread th1 = new Thread(r,"thread-a"); Thread th2 = new Thread(r,"thread-b"); th1.start(); th2.start(); } }注:start方法只是启动线程,使线程处于可运行状态,并没有运行。一旦得到cpu,就开始执行重写的run方法。run执行完毕,线程结束。下面再来介绍并发实现的另一种方式,实际上是Runable方式上的封装。在JDK1.5出现之后,Sun发布的多线程并发处理的工具包java.util.concurrentExecutor
并发任务执行器的顶级抽象,只针对Runnable
ExecutorService
对Executor进行扩展,支持Callable和Future
Callable
对Runnable进行扩展,提供了返回值。
Future
阻塞线程,直到Callable返回了值
FutureTask
实现了Callable和Future
可以简单理解为同时是生产者和消费者的类
其它
闭锁、关卡等实现
并发任务使用
声明一个ExecutorService
向ExecutorService 提交一个或多个Callable,并获取Future
从Future中获取Callable的返回结果
项目应用
实际上是一个“大巴车”模型
测试类
public class TestExecutorService { private int SIZE = 10; /** * 计算1+2+...+100. * * @author wuyichen-ghq * @since 2013-12-31 */ @Test public void main() { ExecutorService exeService = Executors.newCachedThreadPool(); // 任务列表,分成1+10、11+20、。。。、91+100 List<FutureTask<Integer>> taskList = new ArrayList<FutureTask<Integer>>( SIZE); for (int i = 0; i < SIZE; i++) { TestFutureTask task = new TestFutureTask(i * 10 + 1, (i + 1) * 10); taskList.add(new FutureTask<Integer>(task)); } // 逐个提交任务(这里可以将任务创建和提交放在一个for里) for (FutureTask<Integer> task : taskList) { exeService.submit(task); } // 逐个获取任务结果 FutureTask<Integer> task = null; // 任务序列号 int taskIndex = 0; try { while (taskIndex < taskList.size()) { task = taskList.get(taskIndex); assert task != null; int result = task.get(); System.out.println(result); taskIndex++; } } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } }task类
public class TestFutureTask implements Callable<Integer>{ private int begin; private int end; /** * TODO:(构造方法描述) * * @author wuyichen-ghq * @since 2013-12-31 * @param i */ public TestFutureTask(int begin,int end) { this.begin = begin; this.end = end; } /** * TODO:(方法描述) * * @author wuyichen-ghq * @since 2013-12-31 * @throws 无 * @see java.util.concurrent.Callable#call() * */ @Override public Integer call() throws Exception { int result = 0; for(int i=begin;i<=end;i++){ result = i + result; } return result; } }
要注意的地方:异常处理ExecutorService有两个方法:submit、execute
that's all!如果文章中什么错误,请与我联系,也欢迎您跟我邮件交流哦!邮箱:wyc_job@163.com
本文出自 “ATIP團戰術策劃部” 博客,请务必保留此出处http://atip3.blog.51cto.com/6312771/1347150
相关文章推荐
- poj 1755 Triathlon(半平面交解可行域)
- 正试图在 os 加载程序锁内执行托管代码。不要尝试在 DllMain 或映像初始化函数内运行托管代码
- 13、手机防盗--向导设置完成界面
- Java 7之基础类型第5篇 - Java字符串类型
- lucene4.5近实时搜索
- 关于asp.net C# 导出Excel文件 打开Excel文件格式与扩展名指定格式不一致的解决办法
- Linux学习笔记19——信号2
- sicily 1144.淘淘摘苹果
- Android Eclipse 注释模板的使用(图文说明)
- thinkphp命名规则
- 生成n对有效的小括号序列
- 在Linux系统环境下修改MySQL的root密码
- webservice的使用
- php不同形式的实现a-z的26个字母的输出
- 并发协程goroutine
- setWindowFlags(Qt::FramelessWindowHint);使得窗体透明的问题解决
- android 遮罩层效果
- 视频 log
- 韦东山视频观后感
- [leetcode]Binary Tree Maximum Path Sum