并发1:任务与线程

并发通常是提高运行在单处理器上的程序的性能。当以单线程运行所有任务时,虽然不会因为切换线程节省资源,但一旦出现阻塞(IO请求等),则在阻塞接触前单线程会发生等待。如果采用并发可在此时切换任务节省时间。(所以没有任务会被阻塞的情况下在单处理器上使用并发并没有意义)
CPU轮流给每个线程任务分配其占用时间。(例外情况是程序运行在多个CPU之上)

创建线程的多种方法:
- 通过extends Thread实现:

public class MyThread extends Thread{
    @Override
    public void run() {
        //do something here
    }
}
//main中启动线程
new MyThread().start();
  • 通过implements Runnable接口实现
public class MyRunnable implements Runnable{
    @Override
    public void run() {
        //do something here
    }
}
//main中启动线程
new Thread(new MyRunnable()).start();
  • 通过implements Callable接口实现:
public class MyCallable implements Callable<Integer>{
    private int id;
    public MyCallable(int id) {
        this.id=id;
    }
    /*Callable接口与Runnable不同点在于实现的是call方法
     * 此方法可return定义好的Callable接口的泛型类型,如此处的Integer
     * 而Runnable的run方法是void的
     * */
    @Override
    public Integer call() throws Exception {
        return id;
    }
}
//main中启动线程
MyCallable myCallable=new MyCallable(1);
//FutureTask是一个实现了Runnable以及Callable的包装类,借助它来创建Thread
FutureTask<Integer> futureTask=new FutureTask<Integer>(myCallable);
new Thread(futureTask).start();
//可获取call的返回值,FutureTask是Future的实现类
futureTask.get();
  • 通过线程池实现:
/*创建一个缓存线程池(执行过程中创建与与所需数量相同的线程,并在开始回收旧线程时停止创建。Cached线程池通常是合理的首选)
*/
ExecutorService executor=Executors.newCachedThreadPool();
/*创建一个固定大小的线程池,例如这里设置为5。假如我们for循环创建50个任务。则总是只会有5个线程在执行。
例如12345,如果2最先执行完毕,线程销毁,那么这时候才会加入新的线程执行13456
*/
ExecutorService executor=Executors.newFixedThreadPool(5);
/*创建一个单一线程池,相当于大小为1的固定线程池,例如我们for循环加入五十个任务,用单一线程池进行执行,会跑完一个任务才会执行下一个任务
*/
ExecutorService executor=Executors.newSingleThreadExecutor();
/*将任务加入线程池进行执行
*/
executor.execute(Runnable runnable);//return void
executor.submit(Callable<T> callable);//return Future<T>
/*取值前先进行判断,因为future.isDone()方法用于检查Future对象是否已经用callable返回值完成了参数化。完成了就可以get()到值,如果未完成时调用get(),则get()方法会阻塞至完成后执行。
*/
if(future.isDone){
    future.get();
}
/*关闭线程池。例如我们在执行线程main中调用此方法意味着当前线程(main)将继续运行shutdown前我们提交的线程任务,并在所有任务完成后尽快退出。
*/
executor.shutdown();

总结
Thread是线程,而Runnable,Callable,以及通过extends Thread重写的run,均是相当于一个任务对象。
我们可以直接在Thread构造参数里传入Runnable任务来创建线程,也可以借助FutureTask来包装Callable创建线程。
线程池是事先设置一定数目的线程存储空间。通过execute加入Runnable任务,or通过submit加入Callable任务。
Callable任务与Runnable任务不同点在于,前者具有返回值。
可通过Future的get()获取。Future接口定义了cancel(),sCancelled(),isDone(),get()等方法用于控制和查询。
FutureTask是Future的具体实现类,(implements RunnableFuture,而RunnableFuture接口又extends Runnable,Future)
SingleThreadExecutor因为同一时刻只有一个线程在执行,所以也能解决共享资源的同步,但更推荐对资源本身进行同步处理(锁机制)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值