线程创建几种方式

创建方式

主要记录一下线程创建的一些方式,后面可以根据不同的需求进行创建。
参考:
死磕 java线程系列之创建线程的8种方式

通过继承Thread类或实现Runnable,Callable接口都可以实现多线程。
采用Runnable,Callable接口的方式创建多线程
(1)线程类只是实现了Runnable接口或Callable接口,还可以继承其它类。
(2)多线程可以共享一个target对象,所以合适多个相同线程来处理同一份资源的情况,从而可以将CPU,代码和数据分开,形成清晰的模型,较好的体现了面向对象的思想。
(3)编程稍微复杂,如果需要访问当前线程,则必须使用Thread.currentThread()方法
采用继承Thread类的方法创建多线程
(1)因为多线程类已经继承了Thread类,所以不能在继承其它父类。
(2)编写简单,如果需要访问当前线程,则无须使用Thread.currentThread()方法,直接使用this即可获得当前线程。

1.继承Thread类

启动多线程的步骤如下:
(1)定义Thread 类的子类,并重写该类的run() 方法,该run() 方法的方法体就代表类线程需要完成的任务。因此把run() 方法称为线程执行体。
(2)创建 Thread 子类的实例,即创建线程对象。
(3)调用线程的star()方法来启动该线程。

@Slf4j
public class DemoThread extends Thread{

    public static void main(String[] args) {
        log.info("主线程开始执行");
        DemoThread demoThread = new DemoThread();
        demoThread.start();
        log.info("主线程执行结束");

    }
    @Override
    public void run() {
        log.info("子线程执行");
    }
}

在这里插入图片描述

2.实现Runnable接口

(1)定义 Runnable 接口的实现类,并重写该接口的run()方法,该run() 方法的方法体同样是该线程的线程执行体。
(2)创建 Runnable 实例类的实例,此实例作为 Thread 的 target 来创建Thread 对象,该Thread 对象才是真正的对象。

@Slf4j
public class DemoRunnable implements Runnable{
    public static void main(String[] args) {
        log.info("主线程执行");
        Thread demoRunnable = new Thread(new DemoRunnable());
        demoRunnable.start();

    }
    @Override
    public void run() {
        log.info("子线程执行");
    }
}

在这里插入图片描述

3.匿名内部类

@Slf4j
public class DemoAnonymous {
    public static void main(String[] args) {

        log.info("主线程执行");
        new Thread(new Runnable() {
            @Override
            public void run() {
                log.info("子线程A执行");
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                log.info("子线程B执行");
            }
        }).start();

    }
}

在这里插入图片描述

4.实现Callabe接口

参考:Java并发编程:Callable、Future和FutureTask

从 java 5 开始,Java 提供了 Callable 接口,该接口是runnable 的增强版,Callable 提供类一个 call() 方法可以作为线程执行体,但是call() 方法的功能更强大。
(1) call() 方法可以有返回值
(2) call() 方法可以声明抛出异常

因此我们完全可以提供一个callable 对象作为Thread的 target ,而该线程的执行体就是该callable 对象的call() 方法。同时 java 5 提供了 Future 接口 来代表Callable 接口里 call() 方法的返回值,并且提供了一个 futureTask 的实现类,该实现类实现类 future 接口,并实现了runnable 接口—可以作为Thread 类的target.

启动步骤如下:
(1)创建callable接口的实现类,并实现call() 方法,该call() 方法将作为线程的执行体,且该call() 方法是有返回值的。
(2)创建 callable实现类的实例,使用 FutureTask 类来包装Callable对象,该FutureTask 对象封装 call() 方法的返回值。
(3)使用FutureTask 对象作为Thread对象的target创建并启动新线程。
(4)调用FutureTask对象的get()方法来获取子线程执行结束后的返回值。

@Slf4j
public class DemoCallabe {

    public static void main(String[] args) throws ExecutionException, InterruptedException {

//        new 接口:这种形式实际上就是生产了该接口的一个实现类,并用该接口来接收
        Callable<Integer> call = new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                log.info("子线程结果计算中..");
                Thread.sleep(2000);
                return 1+8;
            }
        };
        log.info("主线程执行。。。");
        FutureTask<Integer> futureTask = new FutureTask<>(call);
        Thread t = new Thread(futureTask);
        t.start();
        //这里会阻塞,必须等待结果返回
        Integer integer = futureTask.get();
        log.info("得到最终结果为:{}",integer);

    }

}

在这里插入图片描述

5.定时器Timer

@Slf4j
public class DemoTimer {
    public static void main(String[] args) {
        Timer timer = new Timer();
        log.info("主线程执行...");
        //延迟0.3s执行,每隔1s反复执行
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                log.info("子线程执行!");
            }
        }, 300,1000);
        log.info("主线程执行结束...");
    }
}

在这里插入图片描述

6.线程池

6.1 线程池工具
@Slf4j
public class DemoThreadPool {

    public static void main(String[] args) {
        // 创建线程池
        ExecutorService threadPool = Executors.newFixedThreadPool(5);
        log.info("主线程执行..");
        for (int i = 0; i < 10; i++) {
            threadPool.execute(new Runnable() { // 提交多个线程任务,并执行
                @Override
                public void run() {
                    log.info("子线程执行.");
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }

}

在这里插入图片描述

6.2 线程池自定义
@Slf4j
public class DemoThreadPool {

    public static void main(String[] args) {
        //创建等待队列
        BlockingQueue<Runnable> bqueue = new ArrayBlockingQueue<Runnable>(20);
        //创建线程池,池中保存的线程数为3,允许的最大线程数为5
        ThreadPoolExecutor pool = new ThreadPoolExecutor(3,5,50, TimeUnit.MILLISECONDS,bqueue);
        log.info("主线程执行.");
        for (int i = 0; i < 10; i++) {
            pool.execute(new Runnable() {
                @SneakyThrows
                @Override
                public void run() {
                    Thread.sleep(1000);
                    log.info("子线程执行....");
                }
            });
        }
        //关闭线程池
        pool.shutdown();
    }
}

在这里插入图片描述

7.并行计算

使用并行计算的方式,可以提高程序运行的效率,多线程并行执行。

public class DemoStream {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
        // 串行,打印结果为12345
        list.stream().forEach(System.out::print);
        System.out.println();
        // 并行,打印结果随机,比如35214
        list.parallelStream().forEach(System.out::print);

    }
}

在这里插入图片描述

8.spring

后续用到再更新…

@Service
public class CreatingThread08Service {

    @Async
    public void call() {
        System.out.println(Thread.currentThread().getName() + " is running");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值