Skip to content

Commit 8903c0a

Browse files
committed
updates
1 parent 851b9aa commit 8903c0a

3 files changed

Lines changed: 264 additions & 33 deletions

File tree

第5章 多线程/Callable和Future.md

Lines changed: 147 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
##1. Callable
2-
泛型接口,用于获取线程执行完的结果
2+
泛型接口,用于获取线程执行完的结果,Callable的声明如下
33

4-
Callable 接口类似于Runnable,两者都是为那些其实例可能被另一个线程执行的类设计的。但是 Runnable 不会返回结果,并且无法抛出经过检查的异常,而Callable返回结果并且可能抛出异常的任务
4+
```java
5+
public interface Callable<V> {
6+
// 返回 V 类型的结果
7+
V call() throws Exception;
8+
}
9+
```
10+
11+
Callable 接口类似于Runnable,两者都是为那些其实例可能被另一个线程执行的类设计的。但是 Runnable 不会返回结果,并且无法抛出经过检查的异常,而Callable是可返回结果并且可以抛出异常的任务
512

613
```java
714
public class MyCallable implements Callable{
@@ -45,10 +52,27 @@ public class CallableDemo {
4552
```
4653

4754
##2. Future
55+
56+
Future 为线程池提供了一个可管理的任务标准,它提供了对Runnable或Callable任务的执行结果进行取消、查询是否完成、获取结果、设置结果操作
57+
4858
Future 接口表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。计算完成后只能使用get()方法来获取结果,如有必要,计算完成前可以阻塞此方法
4959

50-
Future取得的结果类型和Callable返回的结果类型必须一致,这是通过泛型来实现的。Callable要采用ExecutorService的submit()方法提交,返回的future对象可以取消任务
60+
Future取得的结果类型和Callable返回的结果类型必须一致,这是通过泛型来实现的。Callable要采用ExecutorService的submit()方法提交,返回的future对象可以取消任务。Future声明如下
5161

62+
```java
63+
public interface Future<V> {
64+
boolean cancel(boolean var1);
65+
// 该任务是否已经取消
66+
boolean isCancelled();
67+
// 判断是否已经完成
68+
boolean isDone();
69+
// 获取结果,该方法会阻塞
70+
V get() throws InterruptedException, ExecutionException;
71+
// 获取结果,如果还未完成那么等待,直到timeout或返回结果,该方法会阻塞
72+
V get(long var1, TimeUnit var3) throws InterruptedException, ExecutionException, TimeoutException;
73+
}
74+
```
75+
Future的简单使用
5276
```java
5377
// 创建线程池对象
5478
ExecutorService pool = Executors.newFixedThreadPool(2);
@@ -57,16 +81,20 @@ Future<Integer> future = pool.submit(new MyCallable(100));
5781
Integer i1 = future.get();
5882
pool.shutdown();
5983
```
84+
Future常用方法
6085

61-
| 方法声明 | 功能描述 |
62-
| :----------- | :----- |
63-
| cancel() | 取消任务 |
64-
| isCanceled() | 任务是否取消 |
65-
| isDone() | 任务是否完成 |
66-
| get() | 获取结果 |
86+
| 方法声明 | 功能描述 |
87+
| :----------- | :----------------------- |
88+
| cancel() | 取消任务 |
89+
| isCanceled() | 任务是否取消 |
90+
| isDone() | 任务是否完成 |
91+
| get() | 获取结果,get()方法会阻塞,直到任务返回结果 |
92+
| set() | 设置结果 |
6793

6894
## 3. FutureTask
6995

96+
Future只是定义了一些接口规范,而FutureTask则是它的实现类
97+
7098
```java
7199
public class FutureTask<V> implements RunnableFuture<V>{
72100
// 代码省略
@@ -77,7 +105,117 @@ public interface RunnableFuture<V> extends Runnable, Future<V>{
77105
}
78106
```
79107

108+
FutureTask会像Thread包装Runnable那样对Runnable和Callable<V>进行包装,Runnable和Callable由构造函数注入
109+
110+
```java
111+
public FutureTask(Callable<V> callable) {
112+
if (callable == null)
113+
throw new NullPointerException();
114+
this.callable = callable;
115+
this.state = NEW; // ensure visibility of callable
116+
}
117+
```
118+
119+
```java
120+
public FutureTask(Runnable runnable, V result) {
121+
this.callable = Executors.callable(runnable, result);
122+
this.state = NEW; // ensure visibility of callable
123+
}
124+
```
125+
126+
由于FutureTask实现了Runnable,因此,它既可以通过Thread包装来直接执行,也可以提交给ExecuteService来执行,并且还可以直接通过get()方法获取执行结果,该方法会阻塞,直到结果返回。因此,FutureTask既是Future、Runnable,又是包装了Callable,它是两者的合体
127+
128+
```java
129+
public class FutureDemo {
130+
// 线程池
131+
static ExecutorService mExecutor = Executors.newSingleThreadExecutor();
132+
133+
// main函数
134+
public static void main(String[] args) {
135+
try {
136+
futureWithRunnable();
137+
futureWithCallable();
138+
futureTask();
139+
} catch (Exception e) {
140+
}
141+
}
142+
143+
/**
144+
* 其中Runnable实现的是void run()方法,无返回值;Callable实现的是 V
145+
* call()方法,并且可以返回执行结果。其中Runnable可以提交给Thread来包装下
146+
* ,直接启动一个线程来执行,而Callable则一般都是提交给ExecuteService来执行。
147+
*/
148+
private static void futureWithRunnable() throws InterruptedException, ExecutionException {
149+
// 提交runnable则没有返回值, future没有数据
150+
Future<?> result = mExecutor.submit(new Runnable() {
151+
152+
@Override
153+
public void run() {
154+
fibc(20);
155+
}
156+
});
157+
158+
System.out.println("future result from runnable : " + result.get());
159+
}
160+
161+
private static void futureWithCallable() throws InterruptedException, ExecutionException {
162+
/**
163+
* 提交Callable, 有返回值, future中能够获取返回值
164+
*/
165+
Future<Integer> result2 = mExecutor.submit(new Callable<Integer>() {
166+
@Override
167+
public Integer call() throws Exception {
168+
return fibc(20);
169+
}
170+
});
171+
172+
System.out.println("future result from callable : "
173+
+ result2.get());
174+
}
175+
176+
private static void futureTask() throws InterruptedException, ExecutionException {
177+
/**
178+
* FutureTask则是一个RunnableFuture<V>,即实现了Runnbale又实现了Futrue<V>这两个接口,
179+
* 另外它还可以包装Runnable(实际上会转换为Callable)和Callable
180+
* <V>,所以一般来讲是一个符合体了,它可以通过Thread包装来直接执行,也可以提交给ExecuteService来执行
181+
* ,并且还可以通过v get()返回执行结果,在线程体没有执行完成的时候,主线程一直阻塞等待,执行完则直接返回结果。
182+
*/
183+
FutureTask<Integer> futureTask = new FutureTask<Integer>(
184+
new Callable<Integer>() {
185+
@Override
186+
public Integer call() throws Exception {
187+
return fibc(20);
188+
}
189+
});
190+
// 提交futureTask
191+
mExecutor.submit(futureTask);
192+
System.out.println("future result from futureTask : "
193+
+ futureTask.get());
194+
}
195+
196+
// 效率底下的斐波那契数列, 耗时的操作
197+
private static int fibc(int num) {
198+
if (num == 0) {
199+
return 0;
200+
}
201+
if (num == 1) {
202+
return 1;
203+
}
204+
return fibc(num - 1) + fibc(num - 2);
205+
}
206+
}
207+
```
208+
209+
输出结果
210+
211+
```
212+
future result from runnable : null
213+
future result from Callable : 6765
214+
future result from futureTask : 6765
215+
```
216+
80217
##4. CompletionService
218+
81219
CompletionService用于提交一组Callable任务,其take()方法返回已完成的一个Callable任务对应的Future对象。
82220

83221
示例:这里数据的获取好比同时种了好几块地的麦子,然后等待收割,秋收时,哪块先熟,先收割哪块

第5章 多线程/多线程.md

Lines changed: 96 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -212,9 +212,9 @@ public static ExecutorService newFixedThreadPool(int nThreads)
212212

213213
- 这种线程池的线程可以执行:可以执行Runnable对象或者Callable对象代表的线程。
214214
- 调用如下方法即可
215-
- Future<?> submit(Runnable task)
215+
- Future&lt;?> submit(Runnable task)
216216
提交一个 Runnable 任务用于执行,并返回一个表示该任务的 Future
217-
- <T> Future<T> submit(Callable<T> task)
217+
- &lt;T> Future&lt;T> submit(Callable&lt;T> task)
218218
提交一个Callable任务用于执行,返回一个表示任务的未决结果的 Future
219219
- 结束线程:shutdown() 关闭线程池
220220

@@ -319,14 +319,106 @@ public final void setPriority(int newPriority); //设置线程的优先级
319319
| 方法声明 | 功能描述 |
320320
| :--------------------------- | :--------------------------------------- |
321321
| sleep(long millis) | 线程休眠,让当前线程暂停,进入休眠等待状态 |
322-
| join() | 线程加入,调用该方法的线程会插入优先先执行 |
322+
| join() | 线程加入,等待目标线程执行完之后再继续执行,调用该方法的线程会插入优先先执行 |
323323
| yield() | 线程礼让,暂停当前正在执行的线程对象,并执行其他线程。 |
324324
| setDaemon(boolean on) | 将该线程标记为守护线程(后台线程)或用户线程。<br>当正在运行的线程都是守护线程时,Java 虚拟机退出。 <br>该方法必须在启动线程前调用。 |
325325
| stop() | 让线程停止,过时了,但是还可以使用 |
326326
| interrupt() | 中断线程。 把线程的状态终止,并抛出一个InterruptedException。 |
327327
| setPriority(int newPriority) | 更改线程的优先级 |
328328
| isInterrupted() | 线程是否被中断 |
329329

330+
### join
331+
332+
线程加入,等待目标线程执行完之后再继续执行。阻塞当前调用join函数时所在的线程,直到接收函数执行完毕后再继续执行
333+
334+
```java
335+
Worker worker1 = new Worker("work-1");
336+
Worker worker2 = new Worker("work-2");
337+
338+
worker1.start();
339+
System.out.println("启动线程1");
340+
try {
341+
worker1.join();
342+
System.out.println("启动线程2");
343+
worker2.start();
344+
worker2.join();
345+
} catch (InterruptedException e) {
346+
e.printStackTrace();
347+
}
348+
349+
System.out.println("主线程继续执行");
350+
```
351+
352+
```java
353+
class Worker extends Thread {
354+
355+
public Worker(String name) {
356+
super(name);
357+
}
358+
359+
@Override
360+
public void run() {
361+
try {
362+
Thread.sleep(2000);
363+
} catch (InterruptedException e) {
364+
e.printStackTrace();
365+
}
366+
System.out.println("work in " + getName());
367+
}
368+
}
369+
```
370+
371+
输出结果
372+
373+
```
374+
启动线程1
375+
work in work-1
376+
启动线程2
377+
work in work-2
378+
主线程继续执行
379+
```
380+
381+
### yield
382+
383+
使调用该函数的线程让出执行时间给其它已就绪状态的线程,也就是主动让出线程的执行权给其它的线程
384+
385+
```java
386+
class YieldThread extends Thread {
387+
public YieldThread(String name) {
388+
super(name);
389+
}
390+
391+
public synchronized void run() {
392+
for (int i = 0; i < MAX; i++) {
393+
System.out.printf("%s ,优先级为 : %d ----> %d\n", this.getName(), this.getPriority(), i);
394+
// i整除4时,调用yield
395+
if (i == 2) {
396+
Thread.yield();
397+
}
398+
}
399+
}
400+
}
401+
```
402+
403+
```java
404+
YieldThread t1 = new YieldThread("thread-1");
405+
YieldThread t2 = new YieldThread("thread-2");
406+
t1.start();
407+
t2.start();
408+
```
409+
410+
```
411+
thread-1 ,优先级为:5 ----> 0
412+
thread-1 ,优先级为:5 ----> 1
413+
thread-1 ,优先级为:5 ----> 2
414+
thread-1 ,优先级为:5 ----> 0
415+
thread-1 ,优先级为:5 ----> 1
416+
thread-1 ,优先级为:5 ----> 2
417+
thread-1 ,优先级为:5 ----> 3
418+
thread-1 ,优先级为:5 ----> 4
419+
thread-1 ,优先级为:5 ----> 3
420+
thread-1 ,优先级为:5 ----> 4
421+
```
330422

331423
# **4. 线程的生命周期**
332424

@@ -821,7 +913,7 @@ Thread(ThreadGroup group,Runnable target, String name) // 给线程设置分组
821913

822914
这些方法的返回值是ExecutorService对象,该对象表示一个线程池,可以执行Runnable对象或者Callable对象代表的线程。它提供了如下方法:
823915

824-
- Future<?> submit(Runnable task)
916+
- Future&lt;?> submit(Runnable task)
825917

826918
提交一个Runnable任务用于执行,并返回一个表示该任务的 Future
827919

第8章 网络编程/网络编程.md

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -990,26 +990,27 @@ HttpsURLConnection.setDefaultHostnameVerifier();
990990
```
991991
### HttpURLConnection常用方法
992992

993-
| 方法声明 | 功能描述 |
994-
| :------------------- | :---------------------- |
995-
| addRequestProperty() | 添加请求属性 |
996-
| setRequestMethod() | 设置请求方式 |
997-
| connect() | 连接网络 |
998-
| disconnect() | 断开连接 |
999-
| setDoOutput() | 设置打开连接对象输出流,把要提交的数据写入流中 |
1000-
| setDoInput() | 设置打开连接对象输入流 |
1001-
| setConnectTimeout() | 设置连接超时 |
1002-
| setReadTimeout() | 设置读取超时 |
1003-
| setUseCaches() | 设置是否使用缓存 |
1004-
| getResponseCode() | 获取响应码 |
1005-
| getOutputStream() | 获取输出流 |
1006-
| getInputStream() | 获取输入流 |
1007-
| getErrorStream() | 获取错误流 |
1008-
| getResponseMessage() | 获取响应信息 |
1009-
| getContentLength() | 获取内容长度 |
1010-
| getContentEncoding() | 获取内容编码 |
1011-
| getContentType() | 获取内容类型 |
1012-
| getHeaderFields() | 获取所有的头字段 |
993+
| 方法声明 | 功能描述 |
994+
| :------------------------ | :---------------------- |
995+
| addRequestProperty() | 添加请求属性 |
996+
| setRequestMethod() | 设置请求方式 |
997+
| connect() | 连接网络 |
998+
| disconnect() | 断开连接 |
999+
| setDoOutput() | 设置打开连接对象输出流,把要提交的数据写入流中 |
1000+
| setDoInput() | 设置打开连接对象输入流 |
1001+
| setConnectTimeout() | 设置连接超时 |
1002+
| setReadTimeout() | 设置读取超时 |
1003+
| setUseCaches() | 设置是否使用缓存 |
1004+
| getResponseCode() | 获取响应码 |
1005+
| getOutputStream() | 获取输出流 |
1006+
| getInputStream() | 获取输入流 |
1007+
| getErrorStream() | 获取错误流 |
1008+
| getResponseMessage() | 获取响应信息 |
1009+
| getContentLength() | 获取内容长度 |
1010+
| getContentEncoding() | 获取内容编码 |
1011+
| getContentType() | 获取内容类型 |
1012+
| getHeaderFields() | 获取所有的头字段 |
1013+
| setChunkedStreamingMode() | 指定流的大小,大文件上传时用到 |
10131014

10141015
### setRequestProperty和addRequestProperty的区别
10151016

0 commit comments

Comments
 (0)