一、Future Task类有什么作用、实现了哪些接口?Callabale接口和Runnable接口有什么不同
Future是一个接口, FutureTask类是Future 的一个实现类,并实现了Runnable,因此FutureTask可以传递到线程对象Thread中新建一个线程执行。所以可通过Excutor(线程池) 来执行,也可传递给Thread对象执行。 如果在主线程中需要执行比较耗时的操作时,但又不想阻塞主线程时,可以把这些作业交给Future对象在后台完成,当主线程将来需要时,就可以通过Future对象获得后台作业的计算结果或者执行状态。
FutureTask是为了弥补Thread的不足而设计的,它可以让程序员准确地知道线程什么时候执行完成并获得到线程执行完成后返回的结果。
FutureTask是一种可以取消的异步的计算任务。它的计算是通过Callable实现的,它等价于可以携带结果的Runnable,并且有三个状态:等待、运行和完成。完成包括所有计算以任意的方式结束,包括正常结束、取消和异常。
Executor框架利用FutureTask来完成异步任务,并可以用来进行任何潜在的耗时的计算。
一般FutureTask多用于耗时的计算,主线程可以在完成自己的任务后,再去获取结果。
(Future接口和FutureTask类【FutureTask实现了Runnable和Future接口】_chang_ge的博客-CSDN博客)
与使用Runable相比,Callable功能更强大一些
1.相比run()方法,可以有返回值
2.方法可以抛出异常
3.支持泛型的返回值
4.需要借助FutureTask类,比如获取返回结果
public class CallableTest implements Callable {
@Override
public Object call() throws Exception {
int sum = 0;
for (int i = 0; i < 100; i++) {
sum+=i;
}
return sum;
}
public static void main(String[] args) {
// 创建Callable接口实现类对象
CallableTest callableTest = new CallableTest();
// 将此Callable接口实现类对象作为FutureTask构造器中,创建FutureTask的对象
FutureTask futureTask = new FutureTask(callableTest);
// 将FutrueTask的对象作为参数传递到Thread类的构造器中,创建Thread对象,并start()
Thread t=new Thread(futureTask);
t.start();
try {
// get()返回值为FutureTask构造器参数Callable实现类重写的call()的返回值
Object o = futureTask.get();
System.out.println("总数为:"+o);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
二、线程池编写多线程程序
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler){}
corePoolSize (int) : 为核心线程池大小
maximumPoolSize (int) : 为最大线程池大小
keepAliveTime (long) : 为线程最大空闲时间
unit (TimeUnit) : 为时间单位
workQueue (BlockingQueue) : 为线程等待队列
threadFactory (ThreadFactory) : 为线程创建工坊
handler (RejectedExecutionHandler) : 为拒绝策略
三、volatile关键字的作用
把一个变量声明为volatile(不稳定的),指示JVM这个变量是不稳定的,每次使用它都要到主存中进行读取。一般来说,多线程环境下各线程间共享的变量都应该加volatile修饰
四、Java提供了哪些同步机制来实现互斥
锁的范围尽可能小:能锁对象,就不要锁类,能锁代码块,就不要锁方法。
第一个是 JVM 实现的 synchronized,而另一个是 JDK 实现的 ReentrantLock。
1.1 synchronized 代码块:监视器就是指定的对象
它只作用于同一个对象,如果调用两个对象上的同步代码块,就不会进行同步。
1.2 synchronized 方法:监视器就是this对象
和同步代码块一样,作用于同一个对象。
1.3 synchronized 静态方法:监视器就是相应的类
多个线程调用同一个类的不同对象上的这种同步语句,也会进行同步。
当线程很多时,每个线程都会去判断同步上的锁,这是很耗费资源的,无形中降低程序的运行效率
2.ReentrantLock 是 java.util.concurrent(J.U.C)包中的锁。
import java.util.concurrent.locks.*;
class LockExample{
private final ReentrantLock lock = new ReentrantLock();
public void func(){
lock.lock();
try{
for (int i = 0; i < 10; i++) {
System.out.print(i + " ");
}
}
finally{
lock.unlock();
}
}
}
五、模拟烧水泡茶最优工序
import java.util.Date;
class HotWater implements Runnable{
static Date date = new Date();
public void run(){
int time = 15;
while(time != 0){
System.out.println(date+" 正在烧水");
time--;
try{
Thread.sleep(1000);
}catch (Exception e){
System.out.println("Hotwater is in the Error!");
}
}
}
}
class WashCup1 implements Runnable{
static Date date = new Date();
public void run(){
int time = 1;
while(time != 0){
System.out.println(date+" 正在洗茶壶");
time--;
try{
Thread.sleep(1000);
}catch (Exception e){
System.out.println("WashCup1 is in the Error!");
}
}
}
}
class WashCup2 implements Runnable{
static Date date = new Date();
public void run(){
int time = 2;
while(time != 0){
System.out.println(date+" 正在洗茶杯");
time--;
try{
Thread.sleep(1000);
}catch (Exception e){
System.out.println("WashCup2 is in the Error!");
}
}
}
}
public class Tea implements Runnable{
static Date date = new Date();
public static void main(String[] args) throws Exception{
HotWater h1 = new HotWater();
WashCup1 w1 = new WashCup1();
WashCup2 w2 = new WashCup2();
Tea m1 = new Tea();
Thread t1 = new Thread(h1);
Thread t2 = new Thread(w1);
Thread t3 = new Thread(w2);
Thread t4 = new Thread(m1);
try{
t1.start();
try{
t2.start();
t2.join();
t3.start();
t3.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
t1.join();
}catch (Exception e){
System.out.println("Error!");
}
t4.start();
}
public void run(){
System.out.println(date+" 正在泡茶");
try{
Thread.sleep(1000);
}catch (Exception e){
}
}
}
六、用Java并发包的Lock及Condtion改写例9.11
package com.test;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
class Account{
volatile private int value;
volatile private boolean isMoney=false;
private final ReentrantLock lock=new ReentrantLock();
private Condition condition = lock.newCondition();
void put(int i){
lock.lock();
try {
if(isMoney){
try {
//Conditon中的await()对应Object的wait()
condition.await();
}
catch (Exception e){ }
}
value=value+i;
System.out.println("存入"+i+" 账上金额为:"+value);
isMoney=true;
//Condition中的signal()对应Object的notify()
condition.signal();
}
finally {
lock.unlock();
}
}
int get(int i){
lock.lock();
try{
if(!isMoney){
try {
condition.await();
}
catch (Exception e){ }
}
if(value>i)
value-=i;
else {
i=value;
value=0;
}
System.out.println("取走"+i+" 账上金额为:"+value);
isMoney=false;
condition.signal();
return i;
}
finally {
lock.unlock();
}
}
}
class Save implements Runnable{
private Account a1;
public Save(Account a1){
this.a1=a1;
}
public void run(){
while(true) {
a1.put(100);
}
}
}
class Fetch implements Runnable{
private Account a1;
public Fetch(Account a1){
this.a1=a1;
}
public void run(){
while(true) {
a1.get(100);
}
}
}
public class T{
public static void main(String[] args){
Account a1=new Account();
new Thread(new Save(a1)).start();
new Thread(new Fetch(a1)).start();
}
}