多线程面试常考点

228 阅读2分钟
什么是进程?

进程是系统进程资源分配和调度的独立单位。每一个进程都有它自己的内存空间和系统资源。

为什么还需要线程呢?

引入线程的主要原因是为了提高系统的执行效率,减少处理机的空转时间和调度切换时间,以及便于系统管理。

  • 简单的来说:进程实现多处理非常消耗CPU的资源。
  • 在同一个进程内可以执行多个任务,而这每一个任务我们就可以看为一个线程。
进程和线程

定义

  • 进程是作为资源分配的基本单位。
  • 线程是作为资源调度的基本单位,是程序的的执行单元,是程序使用CPU的基本单位。

线程的3个基本状态

  • 就绪
  • 执行
  • 阻塞

线程的两个基本类型

  • 用户级线程:管理过程全部由用户程序完成
  • 系统级线程:由操作系统内核进行管理
并行和并发

并行

  • 并行性是指同一时刻内发生两个或多个事件
  • 并行是在不同 实体上的多个事件
  • 并行是针对进程

并发

  • 并发性是指同一时间间隔内发生两个或多个事件。
  • 并发是在同一实体上的多个事件。
  • 并发是针对线程
Java实现多线程
  • 继承Thread类,重写run方法
public class MyThread {
    public static void main(String[] args)  {
       Thread thread1 =  new Thread(()->{
           for (int i = 0; i < 200; i++) {
               System.out.println(i);
           }
        });


        Thread thread2 =  new Thread(()->{
            for (int i = 0; i < 200; i++) {
                System.out.println(i);
            }
        });

        thread1.start();
        thread2.start();

    }
}
  • 实现Runnable接口,重写run方法
public class MyRunnable implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 200; i++) {
            System.out.println(i);
        }
    }

    public static void main(String[] args) {
        MyRunnable runnable = new MyRunnable();

        Thread thread1 = new Thread(runnable);
        Thread thread2 = new Thread(runnable);

        thread1.start();
        thread2.start();

    }
}
  • 实现Callable接口,重写call方法
public class MyCallable implements Callable<Integer> {
    @Override
    public Integer call() {
        int num = 0;

        for (int i = 0; i < 10; i++) {
            num += i;
        }
        return num;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
        MyCallable myCallable = new MyCallable();
        FutureTask<Integer> futureTask = new FutureTask<>(myCallable);

        new Thread(futureTask).start();

        int i  =  futureTask.get();
        System.out.println(i);
        
    }
}
  • 也可以使用搭配线程池使用

    public class MyExecutor {
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            ExecutorService executorService = Executors.newCachedThreadPool();
            Future<Integer> submit = executorService.submit(() -> {
                int num = 0;
                for (int i = 0; i < 10; i++) {
                    num += i;
                }
                return num;
            });
            Integer integer = submit.get();
            System.out.println(integer);
            executorService.shutdown();
    
        }
    }
    
run方法和start方法的区别
  • start()用异步启动线程,启动的线程不会立刻运行,而是就绪状态,在等待队列等待CPU调度,只有线程真正被CPU调度才会调用run()方法。因此,start()方法可以实现多线程
  • 直接调用run()方法就相当于调用一个普通的方法,达不到多线程异步执行