第三章 线程
来源:互联网 发布:手机文件加密软件2016 编辑:程序博客网 时间:2024/06/05 09:33
运行线程
Thread t = newThread();
t.start();
这个线程上面也不做,没有意义。
运行线程两个方法:
1、 对Thread类派生子类,覆盖其run()方法(继承Thread,重写run,调用Start)
2、 实现Runnable接口,将Runnable对象传递给Thread构造函数。
派生Thread
实现Runnable接口
从线程返回信息
run()方法和start()方法不返回任何值。
竞态条件
到底会得到正确的结果还是异常,或者是一个挂起的程序,这取决于很多因素,包括程序生成了多少线程,系统的CPU和磁盘的速度,系统使用多少个CPU,以及Java虚拟机为不同线程分配时间所用的算法。这些成为竞态条件。
回调
通过调用主类(即启动这个线程的类)中的一个方法来做到的。这被称为回调(callback),因为线程在完成是反过来调用其创建者。
Future、Callable和Executor
创建一个ExecutorService,它会根据需要为你创建线程。可以向ExecutorService提交Callable任务,对于每个Callable任务,会分别得到一个Future。之后可以向Future请求得到任务的结果。
示例3-9:FindMaxTask
<span style="font-size:18px;">import java.util.concurrent.Callable;class FindMaxTask implements Callable<Integer> { private int[] data; private int start; private int end; FindMaxTask(int[] data, int start, int end) { this.data = data; this.start = start; this.end = end; } public Integer call() { int max = Integer.MIN_VALUE; for (int i = start; i < end; i++) { if (data[i] > max) max = data[i]; } return max; }}</span>
示例3-10:MultithreadedMaxFinder
<span style="font-size:18px;">import java.util.concurrent.*;public class MultithreadedMaxFinder { public static int max(int[] data) throws InterruptedException, ExecutionException { if (data.length == 1) { return data[0]; } else if (data.length == 0) { throw new IllegalArgumentException(); } // split the job into 2 pieces FindMaxTask task1 = new FindMaxTask(data, 0, data.length/2); FindMaxTask task2 = new FindMaxTask(data, data.length/2, data.length); // spawn 2 threads ExecutorService service = Executors.newFixedThreadPool(2); Future<Integer> future1 = service.submit(task1); Future<Integer> future2 = service.submit(task2); return Math.max(future1.get(), future2.get()); }}</span>
同步
同步块
Synchronized(System.out) {
//代码块
}
同步方法
publicsynchronized void writeEntry(String message) throws IOException {
//…
}
同步的替代方式
一:使用局部变量而不是字段
二:使用值不可变变量
三:将非线程安全的类用作为线程安全的类的一个私有字段。
四:使用java.util.concurrent.atomic包中特意设计为保证线程安全但可变的类。
(AtomicInteger,AtomicLong,AtomicBoolean,AtomicIntegerArray,不使用引用变量,而是把对象存储在一个AtomicReference中,对于映射和列表等集合,可以使用java.util.Collections的方法把他们包装在一个线程安全的版本中,例如有一个集合foo,可以用Collections.synchronizedSet(foo)得到这个集合的一个线程安全视图)。
死锁
同步会带来死锁问题。
如果两个线程需要独占访问同样的一个资源集,而每个线程分别有这些资源的不同子集的锁,就会发生死锁。
线程调度
优先级
当一个低优先级线程正在运行,而一个高优先级线程准备运行时,虚拟机会或早或晚暂停这个低优先级线程,让高优先级线程运行。高优先级线程就抢占了低优先级线程。
为了能让其他线程有机会运行,一个线程有10种方式可以暂停或者指示它准备暂停。这包括:
*可以对I/O阻塞
*可以对同步对象阻塞
*可以放弃
*可以休眠
*可以链接另一个线程
*可以等待一个对象
*可以结束
*可以被更高优先级线程抢占
*可以被挂起
*可以停止
线程池和Executor
利用java.util.concurrent中的Executors类,可以非常容易地建立线程池。只需要将各个任务作为一个Runnable对象提交给这个线程池,你将会得到一个Future对象,可以用来检查任务的进度。
示例3-13显示了GZipRunnable类。它包含一个字段来标识要压缩的文件。run()方法会压缩这个文件并返回。
import java.io.*;import java.util.zip.*;public class GZipRunnable implements Runnable { private final File input; public GZipRunnable(File input) { this.input = input; } @Override public void run() { // don't compress an already compressed file if (!input.getName().endsWith(".gz")) { File output = new File(input.getParent(), input.getName() + ".gz"); if (!output.exists()) { // Don't overwrite an existing file try ( // with resources; requires Java 7 InputStream in = new BufferedInputStream(new FileInputStream(input)); OutputStream out = new BufferedOutputStream( new GZIPOutputStream( new FileOutputStream(output))); ) { int b; while ((b = in.read()) != -1) out.write(b); out.flush(); } catch (IOException ex) { System.err.println(ex); } } } } }
示例3-14 GZipThread是主程序。它构造了线程池,线程数固定为4,并迭代代理命令行中列出的所有文件和目录。这些文件以及这些目录中的文件将用来构建一个GZipRunnable。这个runnable提交到线程池,最终由这4个线程之一处理。
import java.io.*;import java.util.concurrent.*;public class GZipAllFiles { public final static int THREAD_COUNT = 4; public static void main(String[] args) { ExecutorService pool = Executors.newFixedThreadPool(THREAD_COUNT); for (String filename : args) { File f = new File(filename); if (f.exists()) { if (f.isDirectory()) { File[] files = f.listFiles(); for (int i = 0; i < files.length; i++) { if (!files[i].isDirectory()) { // don't recurse directories Runnable task = new GZipRunnable(files[i]); pool.submit(task); } } } else { Runnable task = new GZipRunnable(f); pool.submit(task); } } } pool.shutdown(); }}
- 第三章 线程
- 线程第三章
- Java 线程第三版 第三章数据同步 读书笔记
- 第三章(在线程间共享数据)
- 第三章线程同步辅助类
- 第三章 ServerSocket用法详解(主要是线程池)
- 第三章 ServerSocket用法详解(主要是线程池)
- 第三章 线程局部存储 windows程序设计 王艳平版
- Java 线程第三版 第四章 Thread Notification 读书笔记
- Java 线程第三版 第六章 高级同步议题 读书笔记
- Java 线程第三版 第九章 Thread调度 读书笔记
- 第三章 解决UI 线程运行无响应问题
- 第三章 Thread Synchronization Utilities(线程同步工具类)【上】
- 第三章 Thread Synchronization Utilities(线程同步工具类)【下】
- java多线程核心技术 第三章线程间通信
- C# 线程手册 第三章 使用线程 实现一个数据库连接池(实战篇)
- 第三讲:线程和线程池
- 进线程、库、第三范式
- Sublime text 2/3 中 Package Control 的安装与使用方法
- iOS 常识
- 万能删除
- GNU ARM 汇编指令【转】
- 把数组排成最小的数
- 第三章 线程
- UVA10815 - Andy's First Dictionary
- 3.3 msg.c:告警处理
- C#连接mysql数据库插入数据后获取自增长主键ID值
- 求第k个排列组合(Permutation Sequence)
- iOS 中copy的简单理解
- C++第三次作业
- Mysql的主从复制
- oauth2.0