一、进程与线程
进程:是程序的一次执行过程,从代码加载、执行到执行完毕的一个完整过程,这个过程也是进程本身从产生、发展到最后消亡的过程。
一个进程就代表一个程序。操作系统能运行多个同时进程。多进程是实现并发的一种有效手段。
线程:线程和进程一样,都是实现并发的一个基本单位。线程是在进程的基础上进行的进一步的划分。
多线程是说一个进程在执行过程中可以产生多个线程,这些线程可以同时存在、同在运行。
二、java中线程的实现
第一种:继承Thread类,重写run()方法,此方法为线程的主体,
要开启线程需要调用start()方法,而不能直接调用run()方法,若直接调用run()方法不会开启线程,仍然是在单线程里执行。
为什么启动线程不能直接使用run()方法呢?
因为线程的运行需要本机操作系统的支持。下面为start()方法在Thread类中的定义:
public synchronized void start(){ if(threadStatus != 0) throw new IllegalThreadStateException(); ... start0(); ... } PRivate native void start0();一般在重复调用start()方法时会抛出“IllegalThreadStateException”异常,
而且实际上此处真正调用的是start0()方法,此方法在声明处使用的native关键字声明,此关键字表示调用本机的操作系统函数,因为多线程的实现依靠底层操作系统的支持。
第二种:实现Runnable接口
Runnable接口中只定义了run()一个抽象方法。
三、Thread和Runnable
联系:Thread类实现了Runnable接口,下面是Thread类的定义:
由此可见,Thread类中的run()方法调用的是Runnable接口中的run()方法,若是要继承Thread类实现多线程,则必需覆写run()方法。
区别:
继承Thread类不适合多个线程共享资源,因为每创建一个线程对象,每个对象都有自己的属性、方法,也都有自己的run()方法。
实现Runnable接口,方便实现资源共享:可以使用一个实现Runnable接口的类的对象创建多个线程,它们共用一个Runnable对象,共用里面的属性、方法,共用run()方法。
四、线程的状态
1.创建状态:创建一个线程对象后就进入创建状态,此时它已经有了相应的内存空间和其他资源,处于不可运行状态。
2.就绪状态:调用start()方法后就开启了线程,线程进入就绪状态,进入线程队列排队,等待CPU服务,已经具备运行条件。
3.运行状态:处于就绪状态的线程被调用并获得处理器资源时,就进入运行状态,自动调用线程对象的run()方法。
4.阻塞状态:正在运行的线程,被人为挂起或执行一些耗时的输入输出操作时,让出CPU,并暂时中止自己的执行,进入阻塞状态。阻塞时不会进入线程队列排队,直到引起阻塞的事件消除后才进入就绪状态。
5.终止状态:线程调用stop()方法或run()方法结束后,处于死亡状态,不能再继续执行。
五、线程操作的相关方法
操作线程的主要方法在Thread类中:
1.取得和设置线程的名称
Thread类可以通过getName()取得线程的名称,通过setName()设置线程的名称。
线程的名称一般在启动线程前设置,也允许为已经运行的线程设置名称,如果没有设置名称,系统会为其自动分配名称,格式为Thread-X。
Java程序每次运行至少启动几个线程?
每当使用Java命令启动一个程序时,都会启动一个JVM,每一个JVM就是操作系统的一个进程,Java本身就具备了垃圾收集机制,所以在Java运行时至少开启两个线程,一个是main线程,一个是垃圾收集线程。
2.判断线程是否启动
isAlive():判断线程是否活着(已经启动且尚未运行结束)
主线程可能比其他线程先执行完,此时其他线程不会受影响,不会随着主线程的结束而结束。
3.线程的强制运行
在线程操作中,可以使用join()方法让一个线程强制运行,在哪个线程里调用join()方法,就阻塞哪个线程,直到被调用的线程执行结束,才继续执行原先的线程。
4.线程的休眠
当线程A正在运行时,另一个线程B可以通过调用线程A的interrupt()方法中断A的运行;
如果线程的休眠被中断,则被中断线程会抛出InterruptedException异常。
5.后台线程
在Java程序中,只要前台有一个线程在运行,则整个Java进程都不会消失,若设置一个后台线程,这样即使Java进程结束了,此后台线程仍然会继续执行,setDaemon()方法可将一个线程设为后台线程。
6.线程的优先级
所有的线程在运行前都保持在就绪状态,那么此时,哪个优先级高,哪个线程就有可能被调用。
通过setPriority()设置线程的优先级,通过getPriority()获取线程的优先级,线程的优先级的级别有以下三种:
class ThreadTask implements Runnable{ public void run() { for(int i=0;i<5;i++){ try { Thread.sleep(1000); } catch (Exception e) { } System.out.println(Thread.currentThread().getName()+"-->"+i); } }}public class Main { public static void main(String[] args){ Thread t1 = new Thread(new ThreadTask(),"threadA"); Thread t2 = new Thread(new ThreadTask(),"threadB"); Thread t3 = new Thread(new ThreadTask(),"threadC"); t1.setPriority(Thread.MAX_PRIORITY); t2.setPriority(Thread.NORM_PRIORITY); t3.setPriority(Thread.MIN_PRIORITY); t1.start(); t2.start(); t3.start(); }}运行结果:threadA-->0threadC-->0threadB-->0threadA-->1threadB-->1threadC-->1threadA-->2threadB-->2threadC-->2threadB-->3threadC-->3threadA-->3threadB-->4threadA-->4threadC-->4线程会根据其优先级的大小来决定哪一个线程先运行,但并非是优先级高的就一定会先执行,哪个线程先执行最终由CPU的调度决定。
主线程的优先级是NORM_PRIORITY,通过getPriority()返回的值为5,是中等级别。
7.线程的礼让
线程yield()方法可以让暂停一个线程的操作,让给其他线程运行,但是暂停的时长是不确定的。
新闻热点
疑难解答