1.并发工具类是什么
一组用于克服java底层线程问题的类和接口的框架
特别地,低级的并发原语如synchronized和wait()/notify()经常难以正确使用
过于依赖这些并发原语会导致性能问题,从而影响了应用程序的扩展性
java底层的线程功能也并未包含线程池以及信号量这样的高级构造
2.指出并发工具类型位于哪些包下面
java.util.concurrent、java.util.concurrent.atomic、java.util.concurrent.locks
3.给出任务的定义
它的类实现了java.lang.Runnable(一个可运行的任务)或者java.util.concurrent.Callable接口(一个可被调用的任务)
4.给出executor的定义
它的类直接或间接地实现了java.util.concurrent.Executor接口,这样便从任务执行机制中解耦任务的提交操作
5.说明Executor接口的局限性
Executor接口仅仅只关注Runnable接口
也就是说,一个可运行任务是没法简单地向其调用者返回结果值的(因为Runnable的run()方法不会返回结果值)
Executor接口也没有提供一种方式来追踪正在执行中的任务进程、取消正在执行的任务或者确定运行的任务什么时候结束执行
Executor无法执行一组可运行的任务
而且Executor也没有为应用程序提供一种关闭executor的方式(更为正确地关闭executor)
6.如何克服Executor的局限性
ExecutorService接口克服Executor的局限性
7.Runnable的run()方法和Callable的call()方法存在什么区别
run()无法返回结果值,而call()方法可以
run()方法无法抛出受检异常,而call()方法可以
8.判断对错:你可以从Runnable的run()方法中抛出受检和非受检的异常,但是只能从Callable的call()方法中抛出非受检的异常
错
Callable的call()方法中抛出受检和非受检的异常,但是只能从Runnable的run()方法中抛出非受检的异常
9.给出future的定义
future是这样一种对象,它的类实现Future接口
它代表了一种异步的计算并且提供了取消任务、返回任务结果值以及确定任务是否已经结束的方法
10.描述类Executors的newFixedThreadPool()方法
类Executors的newFixedThreadPool()方法创建一个线程池复用固定数量的线程操作一个共享的无限队列
至多有nThreads个线程同时处理任务
如果额外的任务在所有线程都活跃时被提交了,它们会在队列中等待一条可用线程
如果在executor停止之前,任何线程因为执行中的失败而终止,而后续任务的又需要执行的时候,一条新的线程会取代其位置
这些在线程池中的线程会一直存在,直到executor被显式地关闭
11.使用Executors和ExecutorService来重构下面的CountingThreads应用程序
public class CountingThreads {
public static void main(String[] args) {
Runnable r = new Runnable() {
@Override
public void run() {
String name = Thread.currentThread().getName();
int count = 0;
while (true) {
System.out.println(name + ":" + count++);
}
}
};
Thread threadA = new Thread(r);
Thread threadB = new Thread(r);
threadA.start();
threadB.start();
}
}
public class CountingThreads {
public static void main(String[] args) {
Runnable r = new Runnable() {
@Override
public void run() {
String name = Thread.currentThread().getName();
int count = 0;
while (true) {
System.out.println(name + ":" + count++);
}
}
};
ExecutorService executorService = Executors.newFixedThreadPool(2);
executorService.submit(r);
executorService.submit(r);
}
}
12.当你执行前面练习中CountingThreads应用程序时,你会观测到诸如pool-1-thread-1所标识的线程输出
请修改CountingThreads,以便观测名称A和B
提示:你需要使用ThreadFactory
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
public class CountingThreads {
public static void main(String[] args) {
Runnable r = new Runnable() {
@Override
public void run() {
String name = Thread.currentThread().getName();
int count = 0;
while (true) {
System.out.println(name + ":" + count++);
}
}
};
ExecutorService executorService = Executors.newSingleThreadExecutor(new ThreadName("A"));
executorService.submit(r);
executorService = Executors.newSingleThreadExecutor(new ThreadName("B"));
executorService.submit(r);
}
}
class ThreadName implements ThreadFactory {
private volatile String name;
public ThreadName(String name) {
this.name = name;
}
@Override
public Thread newThread(Runnable r) {
return new Thread(r, name);
}
}