进程与线程
线程与进程的比较:
-
线程具有许多传统进程所具有的特征,故又称为轻型进程(Light—Weight Process)或进程元;
-
而把传统的进程称为重型进程(Heavy—Weight Process),它相当于只有一个线程的任务。在引入了线程的操作系统中,通常一个进程都有若干个线程,至少需要一个线程。
二者的区别:
- 进程有独立的进程空间,进程中的数据存放空间(堆空间和栈空间)是独立的。
- 线程的堆空间是共享的,栈空间是独立的,线程消耗的资源也比进程小,相互之间可以影响的(线程之间是可以互相访问数据的)。
创建线程的第一种方式(继承方式):
继承方式资源不能共享,以后就不能再继承其他类了
- 创建一个类,并继承Thread类
- 覆写run方法
public void run(){}
- 创建一个线程对象
MyThread t = new MyThread();
- 启动线程
t.start();
创建线程的第二种方式(实现方式-推荐),使用匿名内部类创建:
- 定义一个类
Mythread
来实现(implements
)Runnable
接口。 - 实现(覆写)
public void run(){}
- 创建线程(Thread)对象并将Runnable对象传进去
Thread t = new Thread(new MyRunnable());
- 启动线程依旧是用线程对象调用start()方法。
t.start();
常用方法
-
获得线程的名字:
String getName();
-
设置线程的名字:
void setName();
-
获取当前线程:
Thread t = Thread.currentThread();
-
构造方法(用于继承方式):
—Thread();
—Thread(String name);
(线程子类提供String参数的构造方法,然后调用父类的构造方法,super(name)
) -
构造方法(用于实现方式):
要先传Runnable
对象target
—Thread(Runnable target);
—Thread(Runnable target,String name);
—匿名对象创建:
new Thread(new Runnable(){
public void run() {
for (int i = 0; i <200; i++) {
System.out.println("匿名对象-->" + i);
}
}
},"OOXX").start();
两种方法的比较:
- A extends Thread:
- 简单
- 不能再继承其他类
- 同份资源不能共享 - A implements Runnable
- 多个线程共享一个目标资源,适合多线程处理同一份资源
- 该类可以继承其他类,也可以实现其他接口
线程的生命周期
- 新建:当程序使用new创建一个线程后,该线程处于新建状态,此时他和其他java对象一样,仅仅由Java虚拟机为其分配内存并初始化成员变量值。
Thread r = new Thread()
- 就绪:当线程对象调用start()方法后,该线程处于就绪状态,线程计入线程队列排队,此时该状态线程并未开始执行,它仅表示可以运行了。至于该线程何时运行,取决于JVM线程调度器的调度。
即,调用 r.start() 方法后完成就绪准备
- 运行:若处于就绪状态的线程获得了CPU,开始执行run()线程执行体,该线程处于执行状态。
- 阻塞:线程运行过程中需要被中断,目的是是其他的线程获得执行的机会。该状态就会进入阻塞状态。
-注意
:阻塞状态不能之间转成运行状态,阻塞状态只能重新进入就绪 状态。
常用方法
1.boolean isAlive()
:用于测试线程是否处于活动状态
- 线程一旦挂了,就不能在使用 start方法启动了!
2. join : 调用 void join()
的线程强制执行
- join方法:调用join方法的线程对象强制运行,该线程强制运行期间,其他线程无法运行,必须等到该线程结束后其他线程才可以运行。
- 有人把这种方式称之为联合线程
- void join(long millis)
该线程只强制运行millis毫秒
3. Daemon 后台线程
- 后台线程:处于后台运行,任务是为其他线程提供服务。也称之为“守护线程”或“精灵线程”。JVM的垃圾回收就是典型的后台线程
- 特点:若所有的前台线程死亡,后台线程自动死亡
t.SetDaemon(turn);
用于设置线程为后台线程,必须在start
方法前!
4.sleep 线程休眠
- 让直行的线程暂停一段时间,进入阻塞状态。
- sleep为静态方法
static void sleep(long millis)
在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)。
5. 优先级
-
每个线程都有优先级,优先级的高低只和线程获得执行机会的次数多少有关
- 并非线程优先级越高就一定先执行,哪个线程的先运行取决于CPU的调度 -
默认情况下
main
线程具有普通优先级5
,而它创建的线程也具有普通优先级 -
Thread对象的
setPriority(int x)
和getPriority()
来设置和获得优先级。MAX_PRIORITY : 值是10 MIN_PRIORITY : 值是1 NORM_PRIORITY : 值是5(主方法默认优先级)
6. yield 线程礼让
- 线程礼让:暂停当前正在执行的线程对象,并执行其他线程
Thread
的静态方法,可以是当前线程暂停,但是不会阻塞该线程,而是进入就绪状态。所以完全有可能:某个线程调用了yield()
之后,线程调度器又把他调度出来重新执行。
7.结束线程
boolean flag = true;//用变量来控制线程
public void run() {
int i = 0;
while (flag) {
if (i == 25) {
flag = false;
}
System.out.println("==" + i);
i++;
}
}
在开发中,通常是用一个boolean变量来结束进程