线程和进程的区别

进程是计算机资源分配的基本单位,线程是CPU调度的基本单位,一个进程中包含了多个线程来完成不同的任务。不同的进程会使用不同的内存空间,在同一个进程中的所有线程可以共享内存空间。线程相对来说更轻量化,线程的上下文切换要比进程的切换效率高。

并发与并行的区别

并发是计算机在同一时间应对多个事情,线程轮流使用CPU。
并行是计算机在同一时间做多个事情,多个线程同时使用CPU。

创建线程的方式

  1. 继承Thread类创建线程
  2. 实现Runnable接口创建线程
  3. 实现Callable接口创建线程
  4. 线程池创建线程

    runnable和callable的区别

    Runnable接口中run()方法没有返回值,而Callable接口中call()方法有返回值,是泛型,和Future、FutureTask配合使用可以实现异步调用。
    同时Callable接口的call()方法允许抛出异常,而Runnable的run()方法的异常只能内部解决。

    run()和start()的区别

    start()用来启动线程,通过该线程调用run方法执行run方法中定义的代码,start()方法只能被调用一次
    run()封装了要被线程执行的代码,可调用多次。

线程状态

线程主要有六种状态,分别为NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED

  • NEW:线程刚被创建,尚未启动。
  • RUNNABLE:线程正在执行。
  • BLOCKED:线程被阻塞,A线程执行时加锁,B线程就是阻塞状态,需要等A线程执行完毕后才能执行B线程。
  • WAITING:线程在等待另一个线程执行特定操作。
  • TIMED_WAITING:线程在等待另一个线程执行特定操作,但是有一个时间限制。
  • TERMINATED:线程已经执行完毕。

线程状态转化

首先创建线程(新建),调用start()方法变成可执行状态,执行完毕后是终止状态。
在可执行状态中如果另一个线程加锁则进入阻塞状态,该线程获得锁之后才可执行。
如果线程调用了wait()方法则进入等待状态,需其他线程调用notify()方法通知后才能继续执行。
如果线程调用了sleep()方法则进入时间等待状态,经过一段时间后自动转化为RUNNABLE状态。

如何保证多线程之间的执行顺序

调用join()方法,假设有t1,t2,t3三个线程。如果我们想让线程按123的顺序走,则我们可以在创建t2线程时使用t1.join()方法,在创建t3线程时使用t2.join()方法,这样就保证了只有t1执行完毕后才会执行t2,t2执行完毕后才会执行t3。

notify()和notifyAll()的区别

notify()方法只唤醒一个随机线程
notifyAll()方法唤醒所有等待该对象的线程。

wait()和sleep()的区别

相同点:wait()和sleep()都可以让线程暂停执行一段时间,进入阻塞状态
不同点:
1.sleep()方法时Thread类中的静态方法,而wait()方法时Object类中的成员方法,每个对象都可以调用。
2.sleep(long)和wait(long) 方法中只要()中规定了参数,则会在相应的时间醒来。如果只是wait()方法则会一直沉睡,直到使用notify()方法唤醒
3.wait必须要先获取wait对象的锁才可以调用,而sleep无限制。wait方法执行后会释放对象锁,允许其他线程获取锁。sleep如果在synchronized代码块中执行,则不会释放锁。

打断运行时的线程

1.使用退出标志,可以定义一个bollean类型的变量,用来判断线程是否需要退出。
2.使用stop强制停止,不推荐
3.使用interrupt()方法中断线程。可以打断正常运行的线程,也可以打断处于wait,sleep,join状态的线程,会抛出InterruptedException异常。