简介
在计算机领域中,我们说的并发(concurrency)是指一些列任务的同时运行。如果一台电脑有多个处理器或者有一个多核处理器,这个同时性是真正意义上的并发;但是一台电脑只有一个单核处理器,这个同时性并不是真正的并发。
现代操作系统都允许多任务的并发:在听歌的时候,同时阅读电子邮件,这种并发属于进程级并发。但在一个进程内也可以有多个同时进行的任务。这种进程内并发的任务称为线程级并发。
与并发相关的概念是并行,有些人认为并行是在多核处理器中使用多线程执行,这里的多核处理器可以是一个多核处理器,也可以是同一台电脑上的多个处理器。另一些人认为并发执行应用的线程是非顺序执行的,相应的,他们认为并行是使用多线程去简化问题,这些线程是按预定顺序执行的。
线程的创建和运行
第一种方式:
Thread thread=new Thread(); thread.start();
第二种方式:
Thread thread=new Thread(new Runnable() {
@Override
public void run() {
}
});
thread.start();
多线程的执行过程:
每个Java程序都至少有一个执行线程。当运行程序的时候,JVM将启动这个执行线程来调用程序的main方法。
当调用Thread对象的start()方法时,另一个执行线程将被创建。因而在我们的程序中,每次调用start方法时,都会创建一个新的线程。
当一个程序的所有线程都运行完成时,更准确的说,当所有非守护线程都运行完成的时候,这个Java程序将宣告结束。如果初始线程(执行main方法的线程)结束了,其余的线程仍将继续执行直到它们运行结束。如果某一个线程调用了system.exit()指令来结束程序的执行,所有的线程将都结束。
对一个实现了Runnable接口的类来说,创建Thread对象并不会创建一个新的执行线程;同样的,调用它的run()方法,也不会创建一个新的执行线程。只有调用它的start()方法时,才会创建一个新的执行线程。
线程信息的获取和设置:
Thread类有一些保存信息的属性,这些属性可以用来标识线程,显示线程的状态或者控制线程的优先级。
- ID:保存了线程的唯一标识符
- Name:保存了线程名称
- Priority:保存了线程对象的优先级,线程的优先级是从1到10,其中1是最低优先级,10是最高优先级。我们并不推荐去改变线程的优先级,然而,在需要的时候,也可以这么做。
- Status:保存了线程的状态。在Java中,线程的状态有6种:new、runnable、blocked、waiting、time waiting或者terminated。
如果没有为线程指定一个名字,JVM将自动给它分配一个名字,格式是Thread_XX,其中XX是一组数字。线程的ID和状态是不允许被修改的,线程类没有提供setId()和setStatus()方法来修改它。
线程的中断
如果一个Java程序有不止一个执行线程,当所有线程都运行结束的时候,这个Java程序才能运行结束;更确切的说应该是所有的非守护线程运行结束时,或者其中一个线程调用了System.exit()方法时,这个Java程序才能结束。如果你想终止一个程序,或者程序的某个用户试图取消线程对象正在运行的任务,就需要结束这个线程。
Java提供了中断机制,我们可以用它来结束一个线程,这种机制要求线程检查它是否被中断了,然后决定是不是相应这个中断请求。线程允许忽略中断请求并且继续运行。
interrupted()和isInterrupted()的异同点
还有一个办法可以检查线程是否已被中断,即Thread类的静态方法interrupted(),用来检查当前执行的线程是否被中断。
isInterrupted和interrupted()方法有一个很大的区别:isInterrupted()不能改变interrupted属性的值,但是后者能设置interrupted属性为false。因为interrupted()是一个静态方法,更推荐使用isInterrupted()方法。
像之前提到的,线程可以忽略中断,但并不是预期的行为。