线程什么意思(线程基本用法)线程(Thread)基本方法清单:
创建线程有三种方式:
继承 Thread 类
实现 Runnable 接口
实现 Callable 接口
通过继承 Thread 类创建线程的步骤:
定义 Thread 类的子类,并覆写该类的 run 方法。run 方法的方法体就代表了线程要完成的任务,因此把 run 方法称为执行体。
创建 Thread 子类的实例,即创建了线程对象。
调用线程对象的 start 方法来启动该线程。
实现 Runnable 接口优于继承 Thread 类,因为:
Java 不支持多重继承,所有的类都只允许继承一个父类,但可以实现多个接口。如果继承了 Thread 类就无法继承其它类,这不利于扩展。
类可能只要求可执行就行,继承整个 Thread 类开销过大。
通过实现 Runnable 接口创建线程的步骤:
定义 Runnable 接口的实现类,并覆写该接口的 run 方法。该 run 方法的方法体同样是该线程的线程执行体。
创建 Runnable 实现类的实例,并以此实例作为 Thread 的 target 来创建 Thread 对象,该 Thread 对象才是真正的线程对象。
调用线程对象的 start 方法来启动该线程。
通过实现 Callable 接口创建线程的步骤:
创建 Callable 接口的实现类,并实现 call 方法。该 call 方法将作为线程执行体,并且有返回值。
创建 Callable 实现类的实例,使用 FutureTask 类来包装 Callable 对象,该 FutureTask 对象封装了该 Callable 对象的 call 方法的返回值。
使用 FutureTask 对象作为 Thread 对象的 target 创建并启动新线程。
调用 FutureTask 对象的 get 方法来获得线程执行结束后的返回值。
run 方法是线程的执行体。
start 方法会启动线程,然后 JVM 会让这个线程去执行 run 方法。
可以。但是如果直接调用 Thread 的 run 方法,它的行为就会和普通的方法一样。
为了在新的线程中执行我们的代码,必须使用 Thread 的 start 方法。
使用 Thread.sleep 方法可以使得当前正在执行的线程进入休眠状态。
使用 Thread.sleep 需要向其传入一个整数值,这个值表示线程将要休眠的毫秒数。
Thread.sleep 方法可能会抛出 InterruptedException,因为异常不能跨线程传播回 main 中,因此必须在本地进行处理。线程中抛出的其它异常也同样需要在本地进行处理。
Thread.yield 方法的调用声明了当前线程已经完成了生命周期中最重要的部分,可以切换给其它线程来执行 。
该方法只是对线程调度器的一个建议,而且也只是建议具有相同优先级的其它线程可以运行。
Thread 中的 stop 方法有缺陷,已废弃。
当一个线程运行时,另一个线程可以直接通过 interrupt 方法中断其运行状态。
如果一个线程的 run 方法执行一个无限循环,并且没有执行 sleep 等会抛出 InterruptedException 的操作,那么调用线程的 interrupt 方法就无法使线程提前结束。
但是调用 interrupt 方法会设置线程的中断标记,此时调用 interrupted 方法会返回 true。因此可以在循环体中使用 interrupted 方法来判断线程是否处于中断状态,从而提前结束线程。
安全地终止线程有两种方法:
定义 volatile 标志位,在 run 方法中使用标志位控制线程终止
使用 interrupt 方法和 Thread.interrupted 方法配合使用来控制线程终止
示例:使用 volatile 标志位控制线程终止
示例:使用 interrupt 方法和 Thread.interrupted 方法配合使用来控制线程终止
什么是守护线程?
守护线程(Daemon Thread)是在后台执行并且不会阻止 JVM 终止的线程。当所有非守护线程结束时,程序也就终止,同时会杀死所有守护线程。
与守护线程(Daemon Thread)相反的,叫用户线程(User Thread),也就是非守护线程。
为什么需要守护线程?
守护线程的优先级比较低,用于为系统中的其它对象和线程提供服务。典型的应用就是垃圾回收器。
如何使用守护线程?
可以使用 isDaemon 方法判断线程是否为守护线程。
可以使用 setDaemon 方法设置线程为守护线程。 正在运行的用户线程无法设置为守护线程,所以 setDaemon 必须在 thread.start 方法之前设置,否则会抛出 llegalThreadStateException 异常; 一个守护线程创建的子线程依然是守护线程。 不要认为所有的应用都可以分配给守护线程来进行服务,比如读写操作或者计算逻辑。
yield 方法 yield 方法会 让线程从 Running 状态转入 Runnable 状态。 当调用了 yield 方法后,只有与当前线程相同或更高优先级的Runnable 状态线程才会获得执行的机会。
sleep 方法 sleep 方法会 让线程从 Running 状态转入 Waiting 状态。 sleep 方法需要指定等待的时间,超过等待时间后,JVM 会将线程从 Waiting 状态转入 Runnable 状态。 当调用了 sleep 方法后,无论什么优先级的线程都可以得到执行机会。 sleep 方法不会释放“锁标志”,也就是说如果有 synchronized 同步块,其他线程仍然不能访问共享数据。
join join 方法会 让线程从 Running 状态转入 Waiting 状态。 当调用了 join 方法后,当前线程必须等待调用 join 方法的线程结束后才能继续执行。
Thread 类的 sleep 和 yield 方法将处理 Running 状态的线程。
所以在其他处于非 Running 状态的线程上执行这两个方法是没有意义的。这就是为什么这些方法是静态的。它们可以在当前正在执行的线程中工作,并避免程序员错误的认为可以在其他非运行线程调用这些方法。
即使设置了线程的优先级,也无法保证高优先级的线程一定先执行。
原因在于线程优先级依赖于操作系统的支持,然而,不同的操作系统支持的线程优先级并不相同,不能很好的和 Java 中线程优先级一一对应。
来源:莫然博客,欢迎分享本文!