面试题——多线程有哪几种实现方式?

这个问题不是很难,这是我面试一个小公司的时候问到的,今天记录下来。

1.第一种,继承Thread类,重写run方法,然后调用start()函数。

案例

public class ExtendsThred extends Thread{
    @Override
    public void run() {
        while (true) {
            System.out.println("当前线程名称:" + this.currentThread().getName());
        }
    }

    public static void main(String[] args) {
        //extendThread线程
        new ExtendsThred().start();

        //main线程
        while (true) {
            System.out.println("当前线程名称:" + currentThread().getName());
        }
    }
}

2.第二种,实现Runnable接口,借助Thread类,把Runnale实现类传入Thread的构造函数,然后条用start(),这是我们常用的一种方法。

案例

public class RunnableThreadTest {

    public class RunnableThread implements Runnable {
        @Override
        public void run() {
            while (true) {

                System.out.println("我是Runnable线程"+Thread.currentThread().getName());
            }
        }
    

    public static void main(String[] args) {
        //runnable线程
        RunnableThread runnable = new RunnableThreadTest().new RunnableThread();
        new Thread(runnable).start();

        //mian线程
        while (true) 再
            System.out.println("我是main线程"+Thread.currentThread().getName());
        }
    }
}

3.第三种,使用内部类的方式,直接new Thread,然后实现run方法,或者new 一个Runnable接口,实现run方法,然后传入Thread的构造方法中,调用start()

案例:

public class InnerThread {
    public static void main(String[] args) {
        //使用Runnable
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    System.out.println("当前线程:" + Thread.currentThread().getName());
                }
            }
        }).start();

        //使用Thread
        new Thread(){
            @Override
            public void run(){
                while (true) {
                    System.out.println("当前线程:" + Thread.currentThread().getName());
                }
            }
        }.start();

        //main线程
        while (true) {
            System.out.println("main");
        }
    }
}

4.第四种:实现Callable接口,然后使用FutureTask包装,再借助Thread类实现。

案例:

public class CallableThreadTest {
    //callable的call方法有返回值
    public class CallableThread<String> implements Callable<String> {
        @Override
        public String call() throws Exception {
            while (true) {
                System.out.println("当前线程:" + Thread.currentThread().getName());
            }
        }
    }

    public static void main(String[] args) {
        //使用Callable、FutureTask包装器,借助Thread实现多线程
        CallableThread<String> callableThread = new CallableThreadTest().new CallableThread<>();
        FutureTask<String> task = new FutureTask<>(callableThread);
        new Thread(task).start();

        while (true) {
            System.out.println("当前线程:" + Thread.currentThread().getName());

        }

    }
}

5.第五种,使用线程池技术,ExecutorService,可以执行有返回值的线程任务,也可以执行没有返回值的线程任务,有返回值的任务使用Callable接口,没有返回值的任务使用Runnable接口

案例

public class ExecutorThreadTest {
    //无返回值线程
    public class RunnableThread implements Runnable{
        @Override
        public void run() {
            while (true) {
                System.out.println("当前为Runnable接口任务线程");
            }
        }
    }

    //有返回值线程
    public class CallableThread implements Callable<Object> {

        @Override
        public Object call() throws Exception {
            while (true) {
                System.out.println("当前为Callable接口任务线程");
            }
        }

    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //通过工具类获得线程池
        ExecutorService executorService = Executors.newFixedThreadPool(5);

        //执行无返回值的线程任务
        executorService.submit(new ExecutorThreadTest().new RunnableThread());

        //执行有返回值的线程任务,一个Future存放一个线程返回的结果。get()方法是阻塞的,没有获得结果就会一直等待。
        for (int i = 0; i < 5; i++) {
            Future result = executorService.submit(new ExecutorThreadTest().new CallableThread());
            System.out.println((String) result.get());
        }
    }
}

6.第六种:基于定时器的方法,使用Timer来完成。可以使线程任务在特定的时间执行,或者每隔一段时间就执行一次。

案例:

public class TimerThread {

    public static void main(String[] args) throws ParseException {
        //指定2021-1-23 03:22:45执行改线程
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        Date date = format.parse("2021-1-23 03:22:45");
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("timer执行");
            }
        }, date);

        //每2秒执行一次
        Timer timer1 = new Timer();
        timer1.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                System.out.println("每隔2秒执行一次");
            }
        },new Date(),2000);
    }

}

当然,我们在实际的项目开发中,一般是使用线程池技术来完成任务。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值