多线程

前言:目前大部分操作系统都是以线程为CPU调度和分派基本单位。多线程在日常程序中运用的还是比较多的,潜在的我们web容器帮我们在http层面可以同时处理多个请求,这些可能多我们是无感的。平常的开发中,我们需要结合业务场景来合理运用多线程,例如大文件的IO操作,大量消息发送,都可以运用多线程来处理,充分利用多核CPU性能。

本文主要介绍2个方面:1:创建线程几种方式,包含Java8方式(建议使用,真的很方便);2.异步的callable接口简介。

一、创建线程的方式

  • 继承Thread类创建线程
  • 实现Runnable接口创建线程
  • 使用Callable和Future创建线程
  • 使用线程池

a.继承Thread类,重写run()

public class Test extends Thread {
    @Override
    public void run() {
        System.out.println("hello,word!");
    }
    public static void main(String[] args) {
        Test test = new Test();
        test.start();
    }
}

b.实现Runnable接口创建线程

public class Test implements Runnable {
    @Override
    public void run() {
        System.out.println("hello,word!");
    }
    public static void main(String[] args) {
        Thread thread = new Thread(new Test());
        thread.start();
    }
}
//Java 8 lambda写法
public class Test {
    public static void main(String[] args) {
        Thread thread = new Thread(
                () -> System.out.println("hello,word!"));
        thread.start();
    }
}

c.使用Callable和Future创建线程

public class Test implements Callable<String> {
    @Override
    public String call() throws Exception {
        return "hello,word!";
    }

    public static void main(String[] args) {
        Callable<String> test = new Test();
        try {
            FutureTask<String> futureTask = new FutureTask<>(test);
            Thread thread = new Thread(futureTask);
            thread.run();
            System.out.println(futureTask.get());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
//java8 lambda匿名类写法
public class Test {
    public static void main(String[] args) {
        FutureTask<String> futureTask=new FutureTask<>(()->"hello,word!");
        Thread thread = new Thread(futureTask);
        thread.start();
        try {
            System.out.println(futureTask.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

d.使用线程池

public class Test {
    public static void main(String[] args) {
        FutureTask<String> futureTask=new FutureTask<>(()->"hello,word!");
        ExecutorService service=Executors.newFixedThreadPool(2);
        service.submit(futureTask);
        try {
            System.out.println( futureTask.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

二、Callable小说

Callable和Runnbale一样代表着任务,区别在于Callable有返回值并且可以抛出异常!Callable是一种可以返回结果的任务,这是它与Runnable的区别,但是通过适配器模式可以使Runnable与Callable类似。Future代表了一个异步的计算,可以从中得到计算结果、查看计算状态,其实现FutureTask可以被提交给Executor执行,多个线程可以从中得到计算结果。Callable和Future是配合使用的,当从Future中get结果时,如果结果还没被计算出来,那么线程将会被挂起,FutureTak内部使用一个单链表维持等待的线程;当计算结果出来后,将会对等待线程解除挂起,等待线程就都可以得到计算结果了。

Future接口、FutureTask类

Future是一个接口,代表了一个异步计算的结果。接口中的方法用来检查计算是否完成、等待完成和得到计算的结果。当计算完成后,只能通过get()方法得到结果,get方法会阻塞直到结果准备好了。如果想取消,那么调用cancel()方法。其他方法用于确定任务是正常完成还是取消了。一旦计算完成了,那么这个计算就不能被取消。

FutureTask类实现了RunnableFuture接口,而RunnnableFuture接口继承了Runnable和Future接口,所以说FutureTask是一个提供异步计算的结果的任务。 FutureTask可以用来包装Callable或者Runnbale对象。因为FutureTask实现了Runnable接口,所以FutureTask也可以被提交给Executor。

//FutureTask 2构造方法
public FutureTask(Callable<V> callable) {
        if (callable == null)
            throw new NullPointerException();
        this.callable = callable;
        this.state = NEW;       // ensure visibility of callable
    }

    public FutureTask(Runnable runnable, V result) {
        this.callable = Executors.callable(runnable, result);
        this.state = NEW;       // ensure visibility of callable
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值