前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >面试系列之-线程创建方法(JAVA基础)

面试系列之-线程创建方法(JAVA基础)

作者头像
用户4283147
发布2023-08-21 20:19:09
1120
发布2023-08-21 20:19:09
举报
文章被收录于专栏:对线JAVA面试对线JAVA面试
  1. 继承Thread类创建线程类

(1)需要继承Thread类,创建一个新的线程类;

(2)同时重写run()方法,将需要并发执行的业务代码编写在run()方法中;

代码语言:javascript
复制
public class CreateDemo {
    public static final int MAX_TURN = 5;
    public static String getCurThreadName() {
        return Thread.currentThread().getName();
    }
    //线程的编号
    static int threadNo = 1;
    static class DemoThread extends Thread { //①
        public DemoThread() {
            super("DemoThread-" + threadNo++); //②
        }
        public void run() { //③
            for (int i = 1; i < MAX_TURN; i++) {
                Print.cfo(getName() + ", 轮次:" + i);
            }
            Print.cfo(getName() + " 运行结束.");
        }
    }
    public static void main(String args[]) throws InterruptedException {
        Thread thread = null;
        //方法一:使用Thread子类创建和启动线程
        for (int i = 0; i < 2; i++) {
            thread = new DemoThread();
            thread.start();
        }
        Print.cfo(getCurThreadName() + " 运行结束.");
    }
}
  1. 实现Runnable接口创建线程目标类

2.1 通过匿名类创建Runnable线程目标类

代码语言:javascript
复制
public class CreateDemo2 {
    public static final int MAX_TURN = 5;
    static int threadNo = 1;
    public static void main(String args[]) throws InterruptedException {
        Thread thread = null;
        //使用Runnable的匿名类创建和启动线程
        for (int i = 0; i < 2; i++) {
            thread = new Thread(new Runnable() { //① 匿名实例
                @Override
                public void run() { //② 异步执行的业务逻辑
                    for (int j = 1; j < MAX_TURN; j++) {
                        Print.cfo(getCurThreadName() + ", 轮次:" + j);
                    }
                    Print.cfo(getCurThreadName() + " 运行结束.");
                }
            }, "RunnableThread" + threadNo++);
            thread.start();
        }
        Print.cfo(getCurThreadName() + " 运行结束.");
    }
}

2.2 实现Runnable接口的方式创建线程目标类

代码语言:javascript
复制
package com.crazymakercircle.multithread.basic.create;
// 省略import
public class SalesDemo{
    public static final int MAX_AMOUNT = 5; //商品数量
    //商店商品类(销售线程类),一个商品一个销售线程,每个线程异步销售4次
    static class StoreGoods extends Thread{
        StoreGoods(String name){
            super(name);
        }
        private int goodsAmount = MAX_AMOUNT;
        public void run(){
            for (int i = 0; i <= MAX_AMOUNT; i++){
                if (this.goodsAmount > 0){
                    Print.cfo(getCurThreadName() + " 卖出一件,还剩:"
                              + (--goodsAmount));
                    sleepMilliSeconds(10);
                }
            }
            Print.cfo(getCurThreadName() + " 运行结束.");
        }
    }
    //商场商品类(target销售线程的目标类),一个商品最多销售4次,可以多人销售
    static class MallGoods implements Runnable{
        //多人销售可能导致数据出错,使用原子数据类型保障数据安全
        private AtomicInteger goodsAmount = new AtomicInteger(MAX_AMOUNT);
        public void run(){
            for (int i = 0; i <= MAX_AMOUNT; i++){
                if (this.goodsAmount.get() > 0){
                    Print.cfo(getCurThreadName() + " 卖出一件,还剩:"
                              + (goodsAmount.decrementAndGet()));
                    sleepMilliSeconds(10);
                }
            }
            Print.cfo(getCurThreadName() + " 运行结束.");
        }
    }
    public static void main(String args[]) throws InterruptedException{
        Print.hint("商店版本的销售");
        for (int i = 1; i <= 2; i++){
            Thread thread = null;
            thread = new StoreGoods("店员-" + i);
            thread.start();
        }
        Thread.sleep(1000);
        Print.hint("商场版本的销售");
        MallGoods mallGoods = new MallGoods();
        for (int i = 1; i <= 2; i++){
            Thread thread = null;
            thread = new Thread(mallGoods, "商场销售员-" + i);
            thread.start();
        }
        Print.cfo(getCurThreadName() + " 运行结束.");
    }
}
  1. 使用Callable和FutureTask创建线程

对Future接口的主要方法详细说明如下:

·V get():获取异步任务执行的结果。注意,这个方法的调用是阻塞性的。如果异步任务没有执行完成,异步结果获取线程(调用线程)会一直被阻塞,一直阻塞到异步任务执行完成,其异步结果返回给调用线程。

·V get(Long timeout,TimeUnit unit):设置时限,(调用线程)阻塞性地获取异步任务执行的结果。该方法的调用也是阻塞性的,但是结果获取线程(调用线程)会有一个阻塞时长限制,不会无限制地阻塞和等待,如果其阻塞时间超过设定的timeout时间,该方法将抛出异常,调用线程可捕获此异常。

·boolean isDone():获取异步任务的执行状态。如果任务执行结束,就返回true。

·boolean isCancelled():获取异步任务的取消状态。如果任务完成前被取消,就返回true。

·boolean cancel(boolean mayInterruptRunning):取消异步任务的执行。

FutureTask类和Callable接口的联合使用可以创建能够获取异步执行结果的线程:

(1)创建一个Callable接口的实现类,并实现其call()方法,编写好异步执行的具体逻辑,可以有返回值。

(2)使用Callable实现类的实例构造一个FutureTask实例。

(3)使用FutureTask实例作为Thread构造器的target入参,构造新的Thread线程实例。

(4)调用Thread实例的start()方法启动新线程,启动新线程的run()方法并发执行。其内部的执行过程为:启动Thread实例的run()方法并发执行后,会执行FutureTask实例的run()方法,最终会并发执行Callable实现类的call()方法。

(5)调用FutureTask对象的get()方法阻塞性地获得并发线程的执行结果。

代码语言:javascript
复制
public class CreateDemo3 {
    public static final int MAX_TURN = 5;
    public static final int COMPUTE_TIMES = 100000000;
    //①创建一个 Callable 接口的实现类
    static class ReturnableTask implements Callable<Long> {
        //②编写好异步执行的具体逻辑,可以有返回值
        public Long call() throws Exception{
            long startTime = System.currentTimeMillis();
            Print.cfo(getCurThreadName() + " 线程运行开始.");
            Thread.sleep(1000);
            for (int i = 0; i < COMPUTE_TIMES; i++) {
                int j = i * 10000;
            }
            long used = System.currentTimeMillis() - startTime;
            Print.cfo(getCurThreadName() + " 线程运行结束.");
            return used;
        }
    }
    public static void main(String args[]) throws InterruptedException {
        ReturnableTask task=new ReturnableTask();//③
        FutureTask<Long> futureTask = new FutureTask<Long>(task);//④
        Thread thread = new Thread(futureTask, "returnableThread");//⑤
        thread.start();//⑥
        Thread.sleep(500);
        Print.cfo(getCurThreadName() + " 让子弹飞一会儿.");
        Print.cfo(getCurThreadName() + " 做一点自己的事情.");
        for (int i = 0; i < COMPUTE_TIMES / 2; i++) {
            int j = i * 10000;
        }
        Print.cfo(getCurThreadName() + " 获取并发任务的执行结果.");
        try {
            Print.cfo(thread.getName()+"线程占用时间:"
                      + futureTask.get());//⑦
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        Print.cfo(getCurThreadName() + " 运行结束.");
    }
}
  1. 通过线程池创建线程
代码语言:javascript
复制
public class CreateDemo4{
    public static final int MAX_TURN = 5;
    public static final int COMPUTE_TIMES = 100000000;
    //创建一个包含三个线程的线程池
    private static ExecutorService pool = Executors.newFixedThreadPool(3);
    static class DemoThread implements Runnable{
        @Override
        public void run(){
            for (int j = 1; j < MAX_TURN; j++){
                Print.cfo(getCurThreadName() + ", 轮次:" + j);
                sleepMilliSeconds(10);
            }
        }
    }
    static class ReturnableTask implements Callable<Long>{
        //返回并发执行的时间
        public Long call() throws Exception{
            long startTime = System.currentTimeMillis();
            Print.cfo(getCurThreadName() + " 线程运行开始.");
            for (int j = 1; j < MAX_TURN; j++){
                Print.cfo(getCurThreadName() + ", 轮次:" + j);
                sleepMilliSeconds(10);
            }
            long used = System.currentTimeMillis() - startTime;
            Print.cfo(getCurThreadName() + " 线程运行结束.");
            return used;
        }
    }
    public static void main(String[] args) {
        pool.execute(new DemoThread()); //执行线程实例,无返回
        pool.execute(new Runnable(){
          @Override
          public void run(){
            for (int j = 1; j < MAX_TURN; j++){
              Print.cfo(getCurThreadName() + ", 轮次:" + j);
              sleepMilliSeconds(10);
            }
          }
      });
        //提交Callable 执行目标实例,有返回
        Future future = pool.submit(new ReturnableTask());
        Long result = (Long) future.get();
        Print.cfo("异步任务的执行结果为:" + result);
        sleepSeconds(Integer.MAX_VALUE);
    }
}
本文参与?腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2023-08-19,如有侵权请联系?cloudcommunity@tencent.com 删除

本文分享自 对线JAVA面试 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com