创建多线程的4种方式

Java创建线程的四种方式

1.直接继承Thread类

/**
 * 第一种方式:继承Thread,重写run方法
 */
class MyThread extends Thread{
    @Override
    public void run() {
        for(int i = 0;i <= 1000;i++){
            if(i % 2 == 0){
                System.out.println(i);
            }
        }
    }
}

// 匿名内部类的方式创建线程
new Thread(){
    @Override
    public void run() {
        for(int i = 0;i <= 1000;i++){
            if(i % 2 == 0){
                System.out.println(i);
            }
        }
    }
}.start();

2.实现Runnable的run方法

/**
 * 第二种方式:实现Runnable接口,实现run方法
 */
class MyRunnable implements Runnable{
    @Override
    public void run() {
        for(int i = 0;i <= 1000;i++){
            if(i % 2 == 0){
                System.out.println(i);
            }
        }
    }
}

// 匿名内部类
new Thread(new Runnable(){
    @Override
    public void run() {
        for(int i = 0;i <= 1000;i++){
            if(i % 2 != 0){
                System.out.println(i);
            }
        }
    }
}).start();

// 使用lambda表达式
new Thread(()->{
    for(int i = 0;i <= 1000;i++) {
        if (i % 2 != 0) {
            System.out.println("===");
        }
    }
}).start();

3.实现Callable接口

public interface<T> Callable{
    V call() throws Exception;
}

相较于Runnable接口,Callable接口有以下的优点

  • 方法有返回值,支持泛型的返回值
  • 可以抛出异常
// 实现Callable接口的call方法
class MyThread implements Callable<Integer>{
    @Override
    public Integer call() throws Exception {
        int sum = 0;
        for (int i = 0;i < 100;i++){
            sum += i;
        }
        return sum;
    }
}

返回值的获取使用FutrueTask

/**
* FutureTask实现了Runnable和Future接口
* 可以将Callable接口包装成Runnable接口以启动线程,
* 实现Future接口以获取返回值
*/
public class FutureTask<V> implements RunnableFuture<V>;
public interface RunnableFuture<V> extends Runnable, Future<V>;


// 将Callable接口包装成FutureTask接口
FutureTask<Integer> task = new FutureTask(new MyThread());
// task实现类Runnable接口,所以可以被run
Thread t1 = new Thread(task);
t1.start();
try {
    // 使用Future接口中的get()方法获取返回值
    System.out.println("sum="+task.get());
} catch (InterruptedException e) {
    e.printStackTrace();
} catch (ExecutionException e) {
    e.printStackTrace();
}

4.使用线程池

线程池的引入

  • 对于需要大量的周期短的线程的任务,如果每次都去创建,又很快的销毁,无疑对于操作系统来说,负担是很大的。所以可以将一定数量的线程放入到线程池当中,需要使用线程时从线程池中取出,线程运行结束又放回到线程池当中,而不是直接销毁。
  • 线程不是创建的越多越好的。可以使用线程池控制线程的数量,发挥多线程的优势

Java中对线程池提供的方法和接口

  • 线程池的创建

    // 执行器工具类
    public class Executors{
        // 该池包含固定数量的线程;空闲线程会一直被保留
        public static ExecutorService newFixedThreadPool(..);
        // 只有一个线程的 “池”, 该线程顺序执行每一个提交的任务
        public static ExecutorService newSingleThreadExecutor(..);
        // 必要时创建新线程;空闲线程会被保留 60 秒
        public static ExecutorService newCachedThreadPool(..);
        // 用于预定执行而构建的固定线程池, 替代 java.util.Timer
        public static ScheduledExecutorService newScheduledThreadPool(..);
        // 用于预定执行而构建的单线程 “池”
        public static ScheduledExecutorService newSingleThreadScheduledExecutor();
        public static ExecutorService newWorkStealingPool(..);
    }
        
    // ExecutorService 接口
    void shutdown(); // 关闭线程池
    
    // submit适用于Callable,有返回值
    // execute适用于Runnable
    <T> Future<T> submit(Callable<T> task);
    <T> Future<T> submit(Runnable task, T result);
    Future<?> submit(Runnable task);
    void execute(Runnable command);
    
  • 简单使用线程池

    // 创建线程池
    ExecutorService executorService = Executors.newCachedThreadPool();
    
    // 将线程提交给线程池
    Future<Integer> future = executorService.submit(new MyThread());
    executorService.submit(new MyThread());
    
    try {
        // 如果需要返回值,可以get获取
        System.out.println(future.get());
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (ExecutionException e) {
        e.printStackTrace();
    }
    
    // 关闭线程池
    executorService.shutdown();
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值