Java高级编程——多线程(JDK5新增创建线程方式Callable,线程池)

一、实现Callable接口

1.1与Runnable相比

与Runnable相比Callable功能更加强大

  • 相比于run()方法,call()可以有返回值
  • 方法可以抛出异常,被外面的操作捕获
  • 支持范型的返回值
  • 需要借助FutureTask类,比如获取返回结果

1.2实现步骤

①创建Callable接口实现类

Callable是一个范型接口

class Thread1 implements Callable {

}

②重写call方法

    @Override
    public Object call() throws Exception {
        int sum = 0;
        for (int i = 1; i <= 100 ; i++) {
            if (i % 2 == 0 ) {
                System.out.println(i);
                sum += i;
            }
        }
        return sum;
    }

③新建实现类对象

Thread1 thread1 = new Thread1();

④将实现类对象作为参数传递待FutureTask的构造器中,创建FutureTask的对象

FutureTask实现了Runnable接口,所以FutureTask的对象也是Runnable对象(实现了Runnable接口),可以交给Thread

FutureTask futureTask = new FutureTask(thread1);

⑤将FutureTask的对象传到Thread的构造器中,创建Thread类的对象并start()

        //FutureTask也实现了Runnable接口
        Thread t1 = new Thread(futureTask);

        t1.start();

⑥获取Callable返回值 futureTask.get()

        try {
            //futureTask.get()获取的是FutureTask构造器参数Callable实现类重写的call()的返回值
            System.out.println(futureTask.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

二、使用线程池

2.1.1 背景

经常创建和销毁、使用量特别大的资源,比如并发情况下的线程,对性能影响很大

2.1.2 思路

提前创好多个线程,放在线程池中,使用时直接获取,使用完放回池中。可以避免频繁创建销毁、实现重复利用。

2.1.3 好处

①提高响应速度:减少了创建新线程的时间
②降低资源消耗:重复利用线程池中线程,不需要每次都创建
③便于线程管理

2.2 创建线程池

方式一、线程池工具类Executors调用方法

        //Executors工具类、线程池的工厂类,用法语创建并返回不同类型的线程池
        //1、创建一个可根据需要创建性线程的线程池
        Executors.newCachedThreadPool();

        //2、创建一个可重用固定线程数的线程池
        Executors.newFixedThreadPool(n);


        //3、创建一个只有一个线程的线程池
        Executors.newSingleThreadExecutor();

        //4、创建一个线程池,它可安排再给定延迟后运行命令或者定期地执行
        应用:定时器
        Executors.newScheduledThreadPool(n);

Executors的底层也是基于线程池的实现类ThreadPoolExecutor创建线程池对象

2.2.1 Executors.newFixedThreadPool(int n);

①创建指定线程数量的线程池

ExecutorService service = Executors.newFixedThreadPool(10);

②新建Runnable或Callable接口实现类,并重写run方法或call方法(新建任务)
Runnable:

class PoolThread implements Runnable{
    @Override
    public void run() {
        for (int i = 1; i <= 100 ; i++) {
            if (i % 2 == 0 ) {
                System.out.println(Thread.currentThread().getName()+":"+i);
            }
        }
    }
}

Callable

class PoolThread1 implements Callable {

    @Override
    public Object call() {
        for (int i = 1; i <= 100 ; i++) {
            if (i % 2 == 0 ) {
                continue;
            }
            System.out.println(Thread.currentThread().getName()+":"+i);
        }
        return null;
    }
}

③ 执行指定的线程操作需要提供实现类对象
excute适用于Runnable对象,submit适用于Callable对象 excute在Excutor中
Runnable

service.execute(new PoolThread());//适合适用于Runnable,参数只能是Runnable

Callable

service.submit(new FutureTask(new PoolThread1()));//返回一个FutureTask

④关闭连接池

service.shutdown();//等待全部任务执行完毕后关闭线程池
service.shutdownNow();//立即关闭线程池,可能造成任务丢失

运行结果

...
pool-1-thread-1:72
pool-1-thread-1:74
pool-1-thread-1:76
pool-1-thread-1:78
pool-1-thread-1:80
pool-1-thread-2:45
pool-1-thread-2:47
pool-1-thread-1:82
pool-1-thread-1:84
pool-1-thread-1:86
...

方式二、JDK5提供代表线程池的接口:ExcutorService

//构造器构造
public ThreadPoolExecutor(int corePoolSize,                      参数说明:  线程池数量(核心线程)>0
							int maximumPoolSize,                            线程池可支持的最大数量 >=核心线程
							long keepAliveTime,                             指定临时线程的最大存活时间 >=0
							TimeUnite unit,                                 指定存活时间的单位,秒,分,时,天  时间单位
							BlockingQueue<Runnable> workQueue,              指定任务队列    不为 null
							ThreadFactory threadFactory,					指定用来创建线程的线程工厂   不为 null
							RejectExecutionHandler handler)                 指定线程忙,任务满时,新任务来了的梳理方式   不为 null

2.3 管理线程池

2.3.1 设置线程池属性

//类型强转
        ThreadPoolExecutor service1 = (ThreadPoolExecutor) service;
        service1.setCorePoolSize(15);
        service1.setKeepAliveTime();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值