《Java编程思想》读书笔记 —— 并发。
第21章 并发
Java 是一种多线程语言,并且提出了并发问题。
并发解决的问题大致可分为两类:速度,设计的可管理性。
基本的线程机制
并发编程使我们可以将程序划分为多个分离的、独立运行的任务。一个线程就是在进程中的一个单一的顺序控制流,因此,单个进程可以拥有多个并发执行的任务,但是你的程序使得每个任务都好像有其自己的 CPU 一样。其底层机制是切分 CPU 的时间。
1、定义任务
线程可以驱动任务,因此你需要一种描述任务的方式,这可以由 Runnable 接口来提供。
public class LiftOff implements Runnable {
protected int countDown = 10; // Default
private static int taskCount = 0;
private final int id = taskCount++;
public LiftOff() {}
public LiftOff(int countDown) {
this.countDown = countDown;
}
public String status() {
return "#" + id + "(" +
(countDown > 0 ? countDown : "Liftoff!") + "), ";
}
public void run() {
while(countDown-- > 0) {
System.out.print(status());
Thread.yield();
}
}
} ///:~
Thread.yield()
的调用是对线程调度器的一种建议,建议线程调度器切换任务。
当从 Runnable 导出一个类时,它必须具有run()方法,但是这个方法并无特殊之处--它不会产生任何内在的线程能力。要实现线程行为,你必须显式将一个线程附着在线程上。
public class MainThread {
public static void main(String[] args) {
LiftOff launch = new LiftOff();
launch.run();
}
} /* Output:
#0(9), #0(8), #0(7), #0(6), #0(5), #0(4), #0(3), #0(2), #0(1), #0(Liftoff!),
*///:~
2、Thread 类
将 Runnable 对象转变为工作任务的传统方式是把它提交给一个 Thread 构造器。下面的示例展示了如何用 Thread 来驱动 LiftOff 对象。
public class BasicThreads {
public static void main(String[] args) {
Thread t = new Thread(new LiftOff());
t.start();
System.out.println("Waiting for LiftOff");
}
} /* Output: (90% match)
Waiting for LiftOff
#0(9), #0(8), #0(7), #0(6), #0(5), #0(4), #0(3), #0(2), #0(1), #0(Liftoff!),
*///:~
3、使用 Executor
import java.util.concurrent.*;
public class CachedThreadPool {
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
for(int i = 0; i < 5; i++)
exec.execute(new LiftOff());
exec.shutdown();
}
} /* Output: (Sample)
#0(9), #0(8), #1(9), #2(9), #3(9), #4(9), #0(7), #1(8), #2(8), #3(8), #4(8), #0(6), #1(7), #2(7), #3(7), #4(7), #0(5), #1(6), #2(6), #3(6), #4(6), #0(4), #1(5), #2(5), #3(5), #4(5), #0(3), #1(4), #2(4), #3(4), #4(4), #0(2), #1(3), #2(3), #3(3), #4(3), #0(1), #1(2), #2(2), #3(2), #4(2), #0(Liftoff!), #1(1), #2(1), #3(1), #4(1), #1(Liftoff!), #2(Liftoff!), #3(Liftoff!), #4(Liftoff!),
*///:~
CachedThreadPool
将为每个任务都创建一个线程,是合理得 Executor 的首选。
FixedThreadPool
可以一次性预先执行代价高昂的线程分配,限制了线程数量。不用为每个任务都固定的付出创建线程的开销,所以省时间。限制线程数量的好处在于防止线程的滥用。
SingleThreadExecutor
用于希望在另一个线程中连续运行的任何事物(长期存活的任务)。例如监听进入的套接字连接的任务(他只有一个线程)。
4、从任务中产生返回值
在 Java SE5 中引入的 Callable 是一种具有类型参数的泛型,它的类型参数表示的是从方法 call() 中返回的值的类型,并且必须使用ExecutorService.submit() 方法调用它。
import java.util.concurrent.*;
import java.util.*;
class TaskWithResult implements Callable<String> {
private int id;
public TaskWithResult(int id) {
this.id = id;
}
public String call() {
return "result of TaskWithResult " + id;
}
}
public class CallableDemo {
public static void main(String[] args) {
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)));
for(Future<String> fs : results)
try {
// get() blocks until completion:
System.out.println(fs.get());
} catch(InterruptedException e) {
System.out.println(e);
return;
} catch(ExecutionException e) {
System.out.println(e);
} finally {
exec.shutdown();
}
}
} /* Output:
result of TaskWithResult 0
result of TaskWithResult 1
result of TaskWithResult 2
result of TaskWithResult 3
result of TaskWithResult 4
result of TaskWithResult 5
result of TaskWithResult 6
result of TaskWithResult 7
result of TaskWithResult 8
result of TaskWithResult 9
*///:~
5、休眠
影响任务行为的一种简单方法是调用 sleep(),这将使任务中止执行给定的时间。
sleep会使得线程睡眠(即阻塞),这使得线程调度器可以切换到另一个线程,进而驱动另一个任务。
6、优先级
调度器将倾向于优先权更高的线程先执行(执行的频率高),但 CPU 处理线程集的顺序还是不确定的。
可以通过 Thread.currentThread().setPriority(int) 设置优先级,getPriority()获取优先级。
7、让步
让步通过调用yield()方法来做出(不过这只是一个暗示,没有任何机制保证它将会被采纳)。
对于任何重要的控制或在调整应用时,都不能依赖于yield()。
8、后台线程
当所有非后台线程结束时,程序也就终止了,同时会杀死进程中的所有后台线程。反过来说,只要有任何非后台线程还在运行,程序就不会终止。
必须在线程启动之前调用 setDaemon() 方法,才能把它设置为后台线程。即:
Thread daemon = new Thread(new SimpleDaemons());
daemon.setDaemon(true);
daemon.start();
共享受限资源
关键字 synchronized
为防止资源冲突提供内置支持。
参考资料
1、java编程思想(读书笔记):21.并发 - CSDN博客
http://blog.csdn.net/he_world/article/details/52902701
2、《Java编程思想》——并发读书笔记 - CSDN博客
http://blog.csdn.net/qq_35362055/article/details/78135854
3、Java编程思想读书笔记一:并发 - CSDN博客
http://blog.csdn.net/jiankunking/article/details/54799830
评论 (0)