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

简介:

相信你已经了解过多线程的概念,不妨咱们来回顾下,做个暖场如何


相关概念

  • 线程、进程  

    依赖包含关系、相似(状态)、区别(内存共享、资源共享、成本)

    进程是操作系统分配资源的基础单位,而线程是CPU执行的基础单位

    线程与线程间是并列且独立的。

  • 线程空间、ThreadLocal、线程上下文

    线程运行时所占用的内存、锁、cpu等资源的一个虚拟视图

    线程的一个局部变量,可以理解为与当前线程绑定的一个map

    线程空间的一个实时状态

  • 线程状态

    创建、运行、阻塞、销毁

    102506481.png

  • 线程与锁

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


线程并发模型

  • 阻塞队列

    当队列不满足操作条件时,操作线程将进入阻塞状态
    get()时,如果队列为空,则阻塞线程,直到成功执行了add()
    add()时,如果队列已满,则阻塞线程,直到成功执行了get()
    最常用的一种并发调度器

    eg :生产者-消费者

  • 闭锁

    闭锁线程转换到“开门”状态之前,任何尝试“进门”的线程都会被阻塞

    eg:登机

  • 关卡

    所有线程都执行到“关卡”点之前,任何尝试“过关”的线程都会被阻塞

    eg:大巴车

线程实现

java多线程实现,有两种方法。继承Thread,实现接口Runable。大多数时候我们采用后者。原因很简单:单继承,多实现,况且java的设计原则有一条是“面向接口编程”。

测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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.concurrent

  • Executor
    并发任务执行器的顶级抽象,只针对Runnable

  • ExecutorService 
    对Executor进行扩展,支持Callable和Future

  • Callable
    对Runnable进行扩展,提供了返回值。

  • Future
    阻塞线程,直到Callable返回了值

  • FutureTask
    实现了Callable和Future
    可以简单理解为同时是生产者和消费者的类

  • 其它
    闭锁、关卡等实现


并发任务使用
声明一个ExecutorService 
向ExecutorService 提交一个或多个Callable,并获取Future
从Future中获取Callable的返回结果
项目应用
实际上是一个“大巴车”模型


测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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


相关文章
|
1月前
|
安全 数据库连接 数据库
连接池的并发和线程安全
连接池的并发和线程安全
|
1月前
|
算法 调度 索引
什么是多任务和线程?用线程写的一个udp同步聊天器
什么是多任务和线程?用线程写的一个udp同步聊天器
30 0
|
2月前
|
Java 调度 开发者
JDK 21中的虚拟线程:轻量级并发的新篇章
本文深入探讨了JDK 21中引入的虚拟线程(Virtual Threads)概念,分析了其背后的设计哲学,以及与传统线程模型的区别。文章还将讨论虚拟线程如何简化并发编程,提高资源利用率,并展示了一些使用虚拟线程进行开发的示例。
|
2月前
|
缓存 监控 Java
线程池的魔法:Java 开发者必备的并发工具
线程池的魔法:Java 开发者必备的并发工具
44 0
|
3月前
|
存储 缓存 并行计算
【面试问题】JDK并发类库提供的线程池实现有哪些?
【1月更文挑战第27天】【面试问题】JDK并发类库提供的线程池实现有哪些?
|
30天前
|
数据采集 存储 Java
「多线程大杀器」Python并发编程利器:ThreadPoolExecutor,让你一次性轻松开启多个线程,秒杀大量任务!
「多线程大杀器」Python并发编程利器:ThreadPoolExecutor,让你一次性轻松开启多个线程,秒杀大量任务!
|
21天前
|
存储 算法 Java
【C/C++ 线程池设计思路】 深入探索线程池设计:任务历史记录的高效管理策略
【C/C++ 线程池设计思路】 深入探索线程池设计:任务历史记录的高效管理策略
67 0
|
4天前
|
Java API 调度
安卓多线程和并发处理:提高应用效率
【4月更文挑战第13天】本文探讨了安卓应用中多线程和并发处理的优化方法,包括使用Thread、AsyncTask、Loader、IntentService、JobScheduler、WorkManager以及线程池。此外,还介绍了RxJava和Kotlin协程作为异步编程工具。理解并恰当运用这些技术能提升应用效率,避免UI卡顿,确保良好用户体验。随着安卓技术发展,更高级的异步处理工具将助力开发者构建高性能应用。
|
12天前
|
Java Spring
定时任务里面的任务多线程操作
该内容是关于Spring Boot中配置异步任务和定时任务的代码示例。首先通过`@Configuration`和`@EnableAsync`开启异步支持,然后定义线程池,如使用`ThreadPoolExecutor`并设置核心线程数、最大线程数等参数。接着,在需要异步执行的方法上添加`@Async`注解。此外,通过`@EnableScheduling`开启定时任务,并使用`@Scheduled`定义具体任务和执行周期。若需指定多个线程池,可以创建不同的`Executor` bean,并在`@Async`中指定线程池名称。
19 2

热门文章

最新文章