1.FutureTask类有什么作用?它实现了哪些接口? Callable接口和Runnable接口有什么不同?
一.FutureTask类有什么作用?它实现了哪些接口?
1.在 Java 中为了编程异步事件,我们使用 Thread 类和 Runnable 接口,它们可以开发并行应用程序。问题是在执行结束时不能返回值。因此,添加了 FutureTaks,Future 和 Callable 类,它们与以前的类具有大致相同的功能,但极大地促进了并行应用程序的开发。由于线程 Thread 只支持 Runnable 构造,于是有了 Future 可以根据 Callable 构建线程。
由于 Future 只是一个接口,无法直接创建对象,因此有了 FutureTask 。
请参阅:
Future:封装并行调用的类,可以取消任务的执行,确定执行是否已成功完成或出错,以及其他操作;
FutureTask:这是 Future 接口的实现,将在并行调用中执行。
Callable:用于实现并行执行的接口。它与 Runnable 接口非常相似,但是它不返回任何值,而 Callable 必须在执行结束时返回一个值。
ExecutorService:用于在创建线程池,开始和取消管理并行执行的线程。
创建线程的3中方式 Thread、Runnable、Callable ,其中 Callable 是有返回结果的。
2.FutureTask实现的接口:Runnable,Callable,Future。
二. Callable接口和Runnable接口有什么不同?
不同点:
1.callable的核心是call方法,允许返回值,runnable的核心是run方法,没有返回值。
2.call方法可以抛出异常,但是run方法不行。
因为runnable是java1.1就有了,所以他不存在返回值,后期在java1.5进行了优化,就出现了callable,就有了返回值和抛异常。
3.callable和runnable都可以应用于executors。而thread类只支持runnable。
相同点:
1.两者都是接口。
2.两者都需要调用Thread.start()启动线程。
2.请查阅JDK自学线程池的相关类,如ThreadPoolExecutor构造器各个参数的意义, 利用线程池编写多线程程序。
hreadPoolExecutor的七个参数:
corePoolSize 核心线程数
MaxPS 最大线程数
keepAliveTime 存活时间
TimeUnit 时间单位
BlockingQueue 任务队列
ThreadFactory 线程工厂
RejectStrategy 拒绝策略
Abort 抛异常
Discard 悄悄扔掉
DiscardOld 扔掉最先的任务
CallerRuns 谁提交任务谁来执行
3.volatile关键字有什么作用?请举例说明。
一个定义为volatile的变量表示这个变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。
精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。
例如:
class Resource implements Runnable {
volatile public int i;
public Resource(int _i){
i = _i;
}
public void run(){
while(true){
if (i>0){
try{
Thread.sleep(200);
}
catch(Exception e){}
i--;
System.out.println(Thread.
currentThread().getName()+" "+i);
}
else{
System.out.println(Thread.
currentThread().getName());
break;
}
}
}
}
public class TestSecurity{
public static void main(String[] args){
Resource m = new Resource(9);
Thread t1 = new Thread(m);
Thread t2 = new Thread(m);
t1.start();
t2.start();
运行结果:
4.Java提供了哪些同步机制来实现互斥?
1.对象监视器(monitor)与synchronized
Synchronized的三种用法:
synchronized 代码块:监视器就是指定的对象。
synchronized 方法:监视器就是this对象。
synchronized 静态方法:监视器就是相应的Class对象。
2. Java并发包中的锁类
接口
ReentrantLock类
5.编写Java程序模拟烧水泡茶最优工序。
package homework.third;
public class MakeTeaThread1 extends Thread{
private MakeTeaThread2 mk2;
public MakeTeaThread1() {
mk2=new MakeTeaThread2();
}
public void run() {
System.out.print(this.getName()+":洗水壶->");
try {
Thread.sleep(1000);
}
catch(Exception e) {}
System.out.println("烧水-------------------");
System.out.print(" |");
mk2.start();
try {
Thread.sleep(15000);
}
catch(Exception e) {}
System.out.println();
System.out.print(Thread.currentThread().getName()+": 泡茶");
}
}
package homework.third;
public class MakeTeaThread2 extends Thread{
public void run() {
System.out.println();
System.out.print(this.getName()+": 洗茶壶->");
try {
Thread.sleep(1000);
}
catch(Exception e) {}
System.out.print("洗茶杯->");
try {
Thread.sleep(2000);
}
catch(Exception e) {}
System.out.println("拿茶叶------");
System.out.print(" ↓");
}
}
package homework.third;
public class MakeTea {
public static void main(String[] args) {
MakeTeaThread1 mk1=new MakeTeaThread1();
mk1.start();
}
}
6.请使用Java并发包的Lock及Conditon改写例9.11。
import java.util.concurrent.locks.*;
class Account{
volatile private int value;
//布尔标志
volatile private boolean isMoney = false;
private final ReentrantLock lock = new ReentrantLock();
// 存钱的 Condition 对象
private Condition SaveCondition = lock.newCondition();
// 取钱的 Condition 对象
private Condition FetchCondition = lock.newCondition();
}
存钱
void put(int i) {
lock.lock(); //使用锁取代同步方法
try{
while(isMoney){
try{
SaveCondition.await(); //存钱线程等待
} catch(Exception e){}
}
value = value + i;
System.out.println("存入"+i+" 账上金额为:"+value);
isMoney = true;//设置标志
FetchCondition.signal(); //唤醒等待资源的取钱线程
} finally {
lock.unlock();
}
}
取钱
int get(int i) {
lock.lock();
try{
while(!isMoney ){
try {
FetchCondition.await(); //取钱线程等待
} catch(Exception e){}
}
if (value>i)
value = value - i;
else {
i = value;
value = 0; }
System.out.println("取走"+i+" 账上金额为:"+value);
isMoney = false;
SaveCondition.signal(); //唤醒等待资源的存钱线程
return i;
} finally {
lock.unlock();}
}