并发 多线程 —— 读书笔记——持续更新中
来源:互联网 发布:xcode上c语言的函数库 编辑:程序博客网 时间:2024/06/14 03:42
这是我读《Java编程思想》时,做的读书笔记,还未完善,持续更新中,主要目的是让自己能够理清其中的知识点。
简介
并发是为了提高运行在单处理器上的程序性能,增加上下文切换(从一个任务切换到另一个任务)的代价,以减少任务或线程阻塞带来的开销。
难点在于协调不同线程驱动的任务之间对这些资源的使用,以使得这些资源不会同时被多个任务访问。
- 简介
- 术语
- 相关类接口
- 任务接口
- 线程执行器类
- 对线程的控制
- 休眠
- 优先级
- 让步
- 后台线程
- 一些便捷的线程创建方式
- 捕获异常
- 资源的共享
术语
在描述将要执行的工作时使用术语“任务”,在引用到驱动任务的具体机制时,使用“线程”。因此,如果在概念级别上讨论系统,用“任务”即可,无须提及驱动机制。
- 任务:某个线程实际要执行的操作,也就是实现了Runnable接口类中的run()方法以及实现了Callable接口中的call()方法。
- 线程:驱动任务的具体机制。如Thread类并不执行任何操作,他指示驱动赋予它的任务。
相关类(接口)
多线程的执行需要用到两种类(接口),一种是描述任务的接口,另一种是描述线程执行器的类,将任务提交给线程执行器并启动线程,即可实现线程的创建和启动。
在非常简单的情况下,继承Thread类的类也可实现任务的定义和线程的启动。
任务接口
- Runnable接口:线程任务定义在实现这个接口的类的run()方法中,它是执行工作的独立任务,并不返回任何值。实现此接口的任务,可用Thread类和Executor类来驱动。
- Callable接口:实现此接口的类,其任务定义在call()方法中,并且在完成任务后能返回值。Callable是一种具有类型参数的泛型,其类型参数就是从call()方法中返回的值。但此接口必须使用ExecutorService.submit()方法调用它,并会返回一个Future对象。
线程执行器类
- Thread:将Runnable对象提交给一个Thread构造器即可实现Runnable对象到工作任务的转变。代码示例如下:
//假设LiftOff为一个实现了Runnable接口的类Thread t = new Thread(new LiftOff());//将任务提交给线程t.start();//启动线程//或new Thread(new LiftOff()).start();
就算像上面第二段代码一样,创建Thread类时并未捕获对其的引用,但每个Thread都“注册”了自己,因此确实有一个对它的引用,而且在它的任务推出其run()并死亡之前,垃圾回收器无法清除它。
- Executor:这个类是客户端和任务之间的一个中介对象,实现了对Thread对象的管理,从而简化了并发编程。Executor允许你管理异部任务的执行二无须显示地管理线程的生命周期。
一般使用ExecutorService类来执行Runnable 对象,它是一个具有服务生命周期的Executor。它是由Executor的静态方法创建的(使用Executors的工厂方法来创建),然后调用execute(Runnable)来提交任务。主要有以下几种线程池:
- CachedThreadPool:为每个任务都创建一个线程;可使用shutdown()方法阻止新线程的提交,但会继续执行之前提交的任务,程序将在这些任务执行完成后尽快推出。
- FixedThreadPool:用有限的线程集来执行所提交的任务;使用这种线程池可一次性预先执行代价高昂的线程分配,限制线程数量。
- SingleThreadExecutor:线程数量为1的FixedThreadPool;用途:
1. 在另一个线程中运行长期存活的任务;
2. 在线程中运行段任务,如更新日志或时间分发线程;
3. 若提交了多个任务,这些任务将排队。
Executor驱动线程代码示例如下:
//Runnable接口 //假设LiftOff为一个实现了Runnable接口的类 ExecutorService exec = Executors.newCachedThreadPool(); for(int i = 0; i < 5; i++) { exec.execute(new LiftOff()); } //Callable接口 ExecutorService exec = Executors.newCachedThreadPool(); ArrayList<Future<String>> results = new ArrayList<Future<String>>(); for(int i = 0; i < 10; i++) { results.add(exec.submit(new TaskWithResult(i))) }
对线程的控制
休眠
- 这会使任务中止执行一定的时间(参数给定)
- 在sleep()期间可以抛出InterruptedException异常
- 如果任务获得了锁,则在sleep()期间任务也不会释放锁
- Java SE5引入了TimeUnit类,这将sleep的调用变得更加显式,如下代码所示
代码示例:
public class SleepingTask extends LiftOff { public void run() { tr { while(countDown-- > 0) { System.out.print(status()); //Old-style: //Thread.sleep(100); //Java SE5/6-style: TImeUnit.MILLISECONDS.sleep(100); } } catch (InterruptedException e) { System.err.println("Interrupted"); } }}
优先级
- 可以设置线程的优先级给调度器以彰显线程的重要性
- 优先级高的线程将优先执行,优先级低的线程也会执行,只是执行频率较低
- 可以通过getPriority()和setPriority()来获取和设置线程的优先级
- 通过调用Thread.currentThread()来获得对驱动该任务的Thread 对象的引用
- 优先级要在run()的开头部分设定
- 为了确保调整优先级之后程序依然可移植至其他平台,只使用MAX_PRIORITY、NORM_PRIORITY和MIN_PRIORITY三种级别
代码示例:
//只给出run()部分public void run() { THread.currentThread().setPriority(priority); while(true) { //执行代码 }}
让步
后台线程
一些便捷的线程创建方式
捕获异常
资源的共享
0 0
- 并发 多线程 —— 读书笔记——持续更新中
- Linux下C编程——读书笔记(持续更新中)
- 书单——持续更新
- 书单——持续更新
- 错误——持续更新
- 问题——持续更新
- Python学习—持续更新
- 收集的一些编程网站——持续更新中......
- mac 系统的一些命令行——持续更新中... ...
- 需要学会使用的工具——持续更新中
- 技术问题收集整理汇总——持续更新中...
- Notepad++小知识——持续更新中......
- Gensim源代码详解——dictionary(持续更新中)
- Gensim源代码详解——utils(持续更新中)
- 编程中踩的坑——持续更新
- 【读书笔记】TiJava——并发
- Android中常用开发工具类—持续更新...
- 计算机网络总结(一)—概述(持续更新中。。。)
- back键监听退出应用的两种方式
- 茶壶在触摸机制下旋转的三种方式
- Spring的事务管理:
- 解读JAVA多线程
- CURL常用命令
- 并发 多线程 —— 读书笔记——持续更新中
- CentOS 7.0 安装 mysql-5.7.12 (一)
- LightOJ 1236 - Pairs Forming LCM(唯一分解定理)
- docker privileged mode
- scala根据经纬度获取两点距离
- 多线程服务器的适用场合
- Linux文本和图形界面的切换
- 爬坑小记-1
- <<数学>>柏拉图多面体---定积分(二)