常见面试题

面试官一般都会问线程都有哪几种创建方式?

应聘者一般都会回调3或者四种。实际上,真正的线程创建方式只有2种。

继承thread类 和 实现runnable接口有什么区别?

实现runnable接口,只是创建任务,可以给多个线程使用,相对来说更加灵活。

run和start方法的区别?

run相当于普通方法直接调用,而start方法才是真正的开启一个线程并执行。

多线程一定比串行执行快吗?

不一定。多线程只有在代码中存在io或者网络传输的情况下才会比串行快。因为io或者网络传输的情况下,此时cpu空间,多线程利用到了cpu的时间片才会使得程序更快响应。而不存在上述的情况下,只会增加线程上下文频繁切换,造成资源的浪费。

yiled,sleep,wait的区别?

sleep是抱着锁睡觉,属于TIME_WAITTING。

怎么停止正在运行的线程?

  1. 使用标记位(jdk推荐使用这种方式)
  2. 使用thread.stop()方法。(该方法已过时,因为使用stop方法,会使得当前线程释放掉已获取到的锁,会导致对象状态不一致的问题,因为锁可以保证操作的原子性。)
  3. 使用thread.interrupt方法。(interrupt方法有很多限制,需要线程自己打断,并且这时候线程不能等待或者阻塞,否则都会抛出异常。)

线程的状态

image.png

New

新生状态,还没有调用start方法

RUNNABLE

运行状态,java线程中有就绪和运行俩个状态,就绪状态就是还没有时间片分配。

BLOCKED

阻塞状态,表示线程阻塞与于锁,也就是存在于多线程访问同步代码块。

WAITTING

等待状态,需要其他线程唤醒或者中断。比如wait操作。

TIME_WAITTING

超时等待状态,有时间的等待。sleep操作。

TERMINATED

终止状态,表示当前线程已经执行完毕。

线程的分类

用户线程

用户线程就是相当于前台线程,jvm需要等待前台线程执行完毕才能停止。

守护线程

守护线程相当于后台线程,jvm不需要等待前台线程执行完毕就可以停止。可以通过下面这种方式来设置。

  1. thread.setDaemon(true);

线程的创建方式

继承thread类

  1. class MyThread extends Thread{
  2. @Override
  3. public void run() {
  4. System.out.println("MyThread1.run");
  5. }
  6. }

实现runnable接口

  1. class MyThread implements Runnable{
  2. @Override
  3. public void run() {
  4. System.out.println("MyThread.run");
  5. }
  6. }

实现callable接口

  1. class Task implements Callable<Integer>{
  2. @Override
  3. public Integer call() throws Exception {
  4. return 1;
  5. }
  6. }
  7. public static void main(String[] args) throws ExecutionException, InterruptedException {
  8. ExecutorService executorService = Executors.newFixedThreadPool(1);
  9. Future<Integer> future = executorService.submit(task);
  10. System.out.println(future.get());
  11. }

通过线程池来创建

  1. public static void main(String[] args) throws ExecutionException, InterruptedException {
  2. ThreadFactory threadFactory = new ThreadFactory() {
  3. @Override
  4. public Thread newThread(Runnable r) {
  5. return new Thread(r);
  6. }
  7. };
  8. Thread thread = threadFactory.newThread(new Runnable() {
  9. @Override
  10. public void run() {
  11. System.out.println("JdbcMain.run");
  12. }
  13. });
  14. thread.start();
  15. System.out.println("JdbcMain.main");
  16. }