您的位置:首页 > 其它

【技术交流】让我们来谈一谈多线程和并发任务

2013-12-31 15:40 211 查看
相信你已经了解过多线程的概念,不妨咱们来回顾下,做个暖场如何

相关概念线程、进程 依赖包含关系、相似(状态)、区别(内存共享、资源共享、成本)进程是操作系统分配资源的基础单位,而线程是CPU执行的基础单位。线程与线程间是并列且独立的。

线程空间、ThreadLocal、线程上下文线程运行时所占用的内存、锁、cpu等资源的一个虚拟视图线程的一个局部变量,可以理解为与当前线程绑定的一个map线程空间的一个实时状态

线程状态创建、运行、阻塞、销毁


线程与锁加锁是为了同步调度
锁的类型:共享锁、互斥锁;只读锁、可写锁
死锁
争夺资源
调度失当

线程并发模型阻塞队列当队列不满足操作条件时,操作线程将进入阻塞状态
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: