你的位置:首页 > 信息动态 > 新闻中心
信息动态
联系我们

Java第九章

2021/11/25 22:54:25

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();}
   }